<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sonny Alves Dias, curious software engineer]]></title><description><![CDATA[Curious software engineer writing about software, kids, street epistemology and game dev]]></description><link>https://sonny.alvesdi.as</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1740974098582/1efafd90-3301-4feb-b610-b6891eb99dee.png</url><title>Sonny Alves Dias, curious software engineer</title><link>https://sonny.alvesdi.as</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 20:46:00 GMT</lastBuildDate><atom:link href="https://sonny.alvesdi.as/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Introduction to programming for kids]]></title><description><![CDATA[It’s the summer holidays, after all. So I wanted to spent some time with my 7 years old daughter to teach her programming. ⌨️
I spent some time before discussing with her some of the basics concept verbally: the different parts of a computer, and bas...]]></description><link>https://sonny.alvesdi.as/introduction-to-programming-for-kids</link><guid isPermaLink="true">https://sonny.alvesdi.as/introduction-to-programming-for-kids</guid><category><![CDATA[Kids]]></category><category><![CDATA[kids learning]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Game Development]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Sat, 26 Jul 2025 13:02:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/adgYQhiBZTs/upload/7d8e3dcf7665b2628a1df0ebadd454e1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s the summer holidays, after all. So I wanted to spent some time with my 7 years old daughter to teach her programming. ⌨️</p>
<p>I spent some time before discussing with her some of the basics concept verbally: the different parts of a computer, and basic elements of procedural programming languages (variable, condition, loops).</p>
<p>And recently, I proposed to practice and code something on the computer together. She was reluctant at first I guess the lectures I gave her before lost her haha.</p>
<h2 id="heading-so-i-decided-to-make-a-small-game-first-to-pique-her-interest">So I decided to make a small game first to pique her interest 😯</h2>
<p>I gave a quick thought and came up with that direction:</p>
<ul>
<li><p>A small text game we can play in console (something I could finish in an hour)</p>
</li>
<li><p>I would be using Ruby (the least boilerplate possible and elegant code for beginners)</p>
</li>
<li><p>The game code would be one file only and linear as much as possible to be easy to read almost like a story with exit points where the player loses (easy to read)</p>
</li>
<li><p>I would use some variables, conditions and one loop to show her actual usage of them (something not too complex to introduce complexity step by step)</p>
</li>
<li><p>And to show her a text game can still be cool I would add some awesome ASCII arts 😎</p>
</li>
</ul>
<h2 id="heading-after-about-an-hour-i-had-a-game">After about an hour I had a game ⌚</h2>
<p>You are an adventurer who just arrived in a city which has been claimed by a terrible dragon who is now living in the castle of the local king.</p>
<p>It’s cliché but simple enough for her to understand and me to come up with a story quickly.</p>
<h2 id="heading-the-dragon-game">The dragon game 🐲</h2>
<h3 id="heading-avatar">Avatar</h3>
<p>It’s a text game, but I still wanted to have a bit of incarnation for the player so that when she tries my game it would be citing her name.</p>
<p>So the code starts with that:</p>
<pre><code class="lang-ruby">puts <span class="hljs-string">"Welcome adventurer, start by entering your name:"</span>

name = ask

clear_screen

puts <span class="hljs-string">"Very well, <span class="hljs-subst">#{name}</span> ! We need your help.. \n"</span>
</code></pre>
<p>We have one variable: <code>name</code> and I hid some of the complexity thanks to Ruby, by defining a function <code>ask</code> and <code>clear_screen</code> in another file that I wouldn’t show to her.</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">ask</span> </span>
  print <span class="hljs-string">"&gt; "</span>
  <span class="hljs-keyword">return</span> gets.chomp
<span class="hljs-keyword">end</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">clear_screen</span></span>
  system(<span class="hljs-string">'clear'</span>) <span class="hljs-params">||</span> system(<span class="hljs-string">'cls'</span>)
<span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-a-good-example-of-simplification-of-the-reality">A good example of simplification of the reality</h3>
<p>Once you entered your name, a character describes the awful situation with the dragon, and ask you to confirm if you are capable of helping them.</p>
<p>The code looks like that:</p>
<pre><code class="lang-ruby">puts <span class="hljs-string">"Are you capable of defeating the dragon ? (yes or no)"</span>

choice = ask

<span class="hljs-keyword">if</span> choice == <span class="hljs-string">"no"</span> 
    print <span class="hljs-string">"Ah !? "</span>
    sleep(<span class="hljs-number">3</span>)
    print <span class="hljs-string">"What a shame..."</span>
    sleep(<span class="hljs-number">3</span>)
    puts <span class="hljs-string">" thanks anyway. Farewell <span class="hljs-subst">#{name}</span>."</span>

    exit
<span class="hljs-keyword">end</span>

print <span class="hljs-string">"Super !"</span>
sleep(<span class="hljs-number">1</span>)
print <span class="hljs-string">" Super ! "</span>
sleep(<span class="hljs-number">1</span>)
puts <span class="hljs-string">"We are saved !"</span>
</code></pre>
<p>There are several things interesting here.</p>
<ul>
<li><p>First we are using a condition the first one so she can a practical example of a condition</p>
</li>
<li><p>Second we use that condition to exit early the game: game over we lose, thanks to <code>exit</code></p>
</li>
<li><p>Third we use <code>sleep(n)</code> to give a bit of tension in the text showing up piece by piece. Combined with <code>print</code> which allows us to keep writing on the same line unlike <code>puts</code></p>
</li>
<li><p>Fourth, an important thing that I discussed with my daughter for a while, we are simplifying the choice! Something we often do in game development or software in general. We do choices on how much of abstraction to use to represent the reality. We have to manage our time, resources to allocate them to the main feature, the main element that will end with the best experience. Hence sometimes creating illusions. Illusion of choice. Thus here, the player answers no, we stop the game. The player says anything but no, the game continues. Obviously we could try to convert the input from the player to lowercase to catch even uppercase, use a regex, or even test for the player input against <code>”yes”</code> with a loop. But nothing of that would serve or improve really the experience of the game!</p>
</li>
</ul>
<h3 id="heading-the-hard-part-a-loop">The hard part: a loop</h3>
<pre><code class="lang-ruby">puts <span class="hljs-string">"Hint: 48 + 21 - 5"</span>
sleep(<span class="hljs-number">1</span>)
puts <span class="hljs-string">"You are trying to enter a code:"</span>

code = -<span class="hljs-number">1</span>

<span class="hljs-keyword">while</span> code != <span class="hljs-number">64</span>
    code = ask_number

    <span class="hljs-keyword">if</span> code != <span class="hljs-number">64</span> 
        puts <span class="hljs-string">"It does not work, try something else..."</span>
    <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>We needed a loop to put in practice what I discussed with her. Here I went with a mathematical operation that the player needs to solve and until the player didn’t give the right answer he can try. We could have may be write it a bit more nicer without the condition inside, but again limited time, so it’s good enough.</p>
<h3 id="heading-some-others-conditions">Some others conditions</h3>
<p>The game continues after with several tough situations where the player has to pick the right decision and we test that using several conditions. To alternate and go a bit further into conditions, I also decided to create a situation with 3 choices, only one winning. By using a if/else if condition.</p>
<pre><code class="lang-ruby">puts <span class="hljs-string">"The dragon starts breathing fire strongly towards you ! Quick, what do you do ?"</span>

puts <span class="hljs-string">"  1. You jump on the left side to avoid the flames."</span>
puts <span class="hljs-string">"  2. You use your shield made in dragon skin."</span>
puts <span class="hljs-string">"  3. You hide yourself behind a box on your right side."</span>

choice = ask_number

<span class="hljs-keyword">if</span> choice == <span class="hljs-number">1</span>
    <span class="hljs-comment"># Some specific bad end </span>
    puts <span class="hljs-string">"..."</span> 
    puts <span class="hljs-string">"Game Over \n"</span>

    exit
<span class="hljs-keyword">elsif</span> choice == <span class="hljs-number">3</span>
    <span class="hljs-comment"># Another specific bad end </span>
    puts <span class="hljs-string">"..."</span>
    puts <span class="hljs-string">"Game Over \n"</span>

    exit
<span class="hljs-keyword">end</span>
</code></pre>
<p>It is interesting I believe to show her that conditions can be more complex. In her game we also used <code>if choice == 1 || choice == 3</code> showing again an example of a more complex condition and a simplification of the game to allocate more resources on the rest of the game too.</p>
<h3 id="heading-adding-juice">Adding juice</h3>
<p>My first draft of my game did not have any ASCII art, but after I thought it would be nice to add a bit of juice, or show her something cool in the middle of the game to break the pattern (<a target="_blank" href="https://lawsofux.com/von-restorff-effect/">https://lawsofux.com/von-restorff-effect/</a>).</p>
<p>So here is an example of a very cool ASCII dragon I found online (thanks to joan stark and IronWing for their art) that I included in my game.</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">dragon_fire</span> </span>
  puts <span class="hljs-string">"                                       \\/"</span>
  puts <span class="hljs-string">"                                       ^`'."</span>
  puts <span class="hljs-string">"                                       ^   `'."</span>
  puts <span class="hljs-string">"             (                         ^      `'."</span>
  puts <span class="hljs-string">"           )  )        \\/              ^         `'."</span>
  puts <span class="hljs-string">"         (   ) @       /^              ^            `'."</span>
  puts <span class="hljs-string">"       )  )) @@  )    /  ^             ^               `'."</span>
  puts <span class="hljs-string">"      ( ( ) )@@      /    ^            ^                  `'."</span>
  puts <span class="hljs-string">"    ))  ( @@ @ )    /      ^           ^                     `'."</span>
  puts <span class="hljs-string">"   ( ( @@@@@(@     /       |\\_/|,      ^                        `'."</span>
  puts <span class="hljs-string">"  )  )@@@(@@@     /      _/~/~/~|C     ^                           `'."</span>
  puts <span class="hljs-string">"((@@@(@@@@@(     /     _(@)~(@)~/\\C    ^                              `'."</span>
  puts <span class="hljs-string">"  ))@@@(@@)@@   /     /~/~/~/~/`\\~`C   ^             __.__               `'."</span>
  puts <span class="hljs-string">"   )@@@@(@@)@@@(     (o~/~o)^,) \\~ \\C  ^          .' -_'-'\"...             `."</span>
  puts <span class="hljs-string">"    ( (@@@)@@@(@@@@@@_~^~^~,-/\\~ \\~ \\C/^        /`-~^,-~-`_~-^`;_           `."</span>
  puts <span class="hljs-string">"      @ )@@@(@@@@@@@   \\^^^/  (`^\\.~^ C^.,  /~^~^~^/_^-_`~-`~-~^\\- /`'-./`'-. ;"</span>
  puts <span class="hljs-string">"       (@ (@@@@(@@      `''  (( ~  .` .,~^~^-`-^~`/'^`-~ _`~-`_^-~\\         ^^"</span>
  puts <span class="hljs-string">"           @jgs@             (((` ~ .-~-\\ ~`-_~`-/_-`~ `- ~-_- `~`;"</span>
  puts <span class="hljs-string">"          /                 /~((((` . ~-~\\` `  ~ |:`-_-~_~`  ~ _`-`;"</span>
  puts <span class="hljs-string">"         /                 /~-((((((`.\\-~-\\ ~`-`~^\\- ^_-~ ~` -_~-_`~`;"</span>
  puts <span class="hljs-string">"        /                 /-~-/(((((((`\\~-~\\~`^-`~`\\ -~`~\\-^ -_~-_`~-`;"</span>
  puts <span class="hljs-string">"       /                 /~-~/  `((((((|-~-|((`.-~.`Y`_,~`\\ `,- ~-_`~-`;"</span>
  puts <span class="hljs-string">"      /              ___/-~-/     `\"\"\"\"|~-~|\"''    /~-^ .'    `:~`-_`~-~`;"</span>
  puts <span class="hljs-string">"     /         _____/  /~-~/           |-~-|      /-~-~.`      `:~^`-_`^-:"</span>
  puts <span class="hljs-string">"    /    _____/        ((((            ((((      (((((`           `:~^-_~-`;"</span>
  puts <span class="hljs-string">"    \\___/                                                          `:_^-~`;"</span>
  puts <span class="hljs-string">"                                                                    `:~-^`:"</span>
  puts <span class="hljs-string">"                                                                  ,`~-~`,`"</span>
  puts <span class="hljs-string">"                                                                 ,\"`~.,'"</span>
  puts <span class="hljs-string">"                                                               ,\"-`,\"`"</span>
  puts <span class="hljs-string">"                                                             ,\"_`,\""</span>
  puts <span class="hljs-string">"                                                            ,\",\"`"</span>
  puts <span class="hljs-string">"                                                         ;~-~_~~;"</span>
  puts <span class="hljs-string">"                                                          '. ~.'    "</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-if-you-want-to-check-out-the-game-of-my-daughter-and-the-dragon-one-i-made">If you want to check out the game of my daughter and the dragon one I made, 🔎</h2>
<p>Their entire code is available here: <a target="_blank" href="https://github.com/SonnyAD/mini-games">https://github.com/SonnyAD/mini-games</a></p>
<p>Note that the games are in French though. So feel free to translate or simply reuse the structure to practice programming with your kid too.</p>
<h2 id="heading-to-conclude">To conclude</h2>
<p>I think that mini text game has been a good introduction to programming and she liked it. So it’s a success I believe. Since that day, we did another session where we added a rock, paper, scissors mini-game inside the game of my daughter. And we will be adding more and more complexity step by step.</p>
]]></content:encoded></item><item><title><![CDATA[How to run an SE Spectrum online?]]></title><description><![CDATA[This article is a follow up on my previous one introducing the concept of SE Spectrum:
https://sonny.alvesdi.as/a-better-way-to-discuss
 

Existing solutions
For long, the easiest way to run a spectrum was to use visual drawing or diagram tools like ...]]></description><link>https://sonny.alvesdi.as/how-to-run-an-se-spectrum-online</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-run-an-se-spectrum-online</guid><category><![CDATA[street-epistemology]]></category><category><![CDATA[software]]></category><category><![CDATA[social network]]></category><category><![CDATA[discussion]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Fri, 04 Jul 2025 07:03:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751612921936/b23f6f08-f78b-458e-93a4-ebd4abfc5766.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>This article is a follow up on my previous one introducing the concept of SE Spectrum:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://sonny.alvesdi.as/a-better-way-to-discuss">https://sonny.alvesdi.as/a-better-way-to-discuss</a></div>
<p> </p>
</blockquote>
<h2 id="heading-existing-solutions">Existing solutions</h2>
<p>For long, the easiest way to run a spectrum was to use visual drawing or diagram tools like <a target="_blank" href="https://miro.com">Miro</a>, <a target="_blank" href="https://docs.google.com/drawings">Google Drawing</a>, <a target="_blank" href="https://excalidraw.com/">Excalidraw</a>, or any equivalent. One, generally the host would prepare a setup with different space labeled from “Strongly disagree” to “Stronly agree”. Then while running the spectrum, people would duplicate or create a small pellet to represent their position visually.</p>
<p>And it would look like that:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751603357354/5f359f65-b3df-435d-a45a-9bfb12e1002e.png" alt="Screenshot of a spectrum running in Excalidraw" class="image--center mx-auto" /></p>
<p>On top of that we would run a voice conferencing tool, like Google Meet, Zoom, Discord, StreamYard, etc.</p>
<h3 id="heading-pain-points">Pain points 🤒</h3>
<ul>
<li><p>These tools are generally for collaborations and everybody has the rights. We often end up modifying or deleting the pellet of someone else by mistake.</p>
</li>
<li><p>You need to go back and forth the diagram tool and the voice conferencing to move your positions or mute/unmute yourself.</p>
</li>
<li><p>It requires a bit of setup to prepare your spectrum.</p>
</li>
<li><p>Often all these tools requires you to sign up and login adding even more friction to start and invite participant in your spectrum (Excalidraw is the best one on that point).</p>
</li>
</ul>
<h2 id="heading-this-is-where-i-decided-to-contribute-and-make-a-dedicated-software-for-spectrum">This is where I decided to contribute and make a dedicated software for Spectrum</h2>
<p>So let me introduce to you <strong>OSR Spectrum</strong>!</p>
<p>It is an application dedicated to running spectrums online. It was initially made for the French non-profit organization “Opinions sur Rue” (OSR) promoting Street Epistemology in France, but I recently added English translation and the software is now ready to welcome more users!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751611677443/3e6438a8-ca09-4695-a06b-55e492d821fa.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-features">Features</h2>
<ul>
<li><p>Can start or join a spectrum with between 2 to 6 participants</p>
</li>
<li><p>No collision, everyone controls only his own pellet</p>
</li>
<li><p>Each spectrum has its own private room/link to share to participants</p>
</li>
<li><p>Integrated text chat including history of the spectrum (positions, new claims, ...)</p>
</li>
<li><p>Integrated voice calls too (still a bit chunky though)</p>
</li>
<li><p>Possible to connect to a live stream chat to get an average vote of the viewers (platforms supported: YouTube, Twitch, and TikTok)</p>
</li>
<li><p>Send emoji reactions or raise hand with an animation alike Zoom, Google Meet, and others</p>
</li>
<li><p>Streamer mode to optimize UI for screen sharing</p>
</li>
<li><p>Localized in English and French</p>
</li>
<li><p>Respect of privacy, nothing is stored it's all in ephemeral memory database. And no login/password.</p>
</li>
<li><p>Open Source software, you can run your own instance</p>
</li>
</ul>
<h2 id="heading-software-goal">Software Goal 🎯</h2>
<p>It's made to be usable as is without the need for anything else thanks to the chat and voice calls included. But you can still definitely use it as you want, if you prefer to use Discord voice channel or StreamYard etc. Opinion sur Rue uses it with StreamYard.</p>
<h2 id="heading-how-to-use-it">How to use it?</h2>
<ol>
<li><p><strong>Find participants</strong></p>
</li>
<li><p>Go to <a target="_blank" href="https://spectrum.utile.space">https://spectrum.utile.space</a></p>
</li>
<li><p>Click on “<strong>Start a Spectrum</strong>”</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751611880586/fa394e1c-fb38-41d4-a2c5-a618166083bc.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Fill your nickname</strong> and optionally an initial claim</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751611917737/b21b44f4-c1b8-4f81-9736-7ba5320f8872.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Once started, click on “<strong>Copy Link</strong>” and send the link to the participants</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751611956921/a119797b-a3e1-4c46-b097-382a8dd18b1d.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Once they joined, they can start to move their pellets and the spectrum is ready to go</p>
</li>
<li><p><em>Optionally, you can activate voice conferencing</em></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751612035235/06b3211d-b1bf-49bb-9afe-06b1f4a3aaaf.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>During the spectrum, also everybody can send emoji or raise hand</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751612105868/25c626ff-6dd2-41d2-9530-ff612b7626e6.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-links">Links</h2>
<h3 id="heading-if-you-want-to-see-how-it-looks-in-real-conditions">If you want to see how it looks in real conditions 🔎</h3>
<p>Here is a video from one of the online Spectrum ran by “<strong>Opinions sur Rue</strong>” <em>(sorry it's in French though ^^)</em>:<br />👉 <a target="_blank" href="https://youtu.be/4JkX0n7C7bU?t=2031">https://youtu.be/4JkX0n7C7bU?t=2031</a></p>
<h3 id="heading-if-you-want-to-run-your-own-instance-or-contribute-here-is-the-github-repository">If you want to run your own instance, or contribute, here is the GitHub repository 🌐</h3>
<p>👉 <a target="_blank" href="https://github.com/Opinions-sur-Rue/spectrum">https://github.com/Opinions-sur-Rue/spectrum</a></p>
<h3 id="heading-if-you-just-want-to-run-a-spectrum-or-test-the-app">If you just want to run a spectrum or test the app 🧪</h3>
<p>You can freely use the instance I am running at: <a target="_blank" href="https://spectrum.utile.space/">https://spectrum.utile.space/</a></p>
<h3 id="heading-i-am-looking-for-more-users-and-feedback-to-continue-to-debug-and-improve-it">I am looking for more users and feedback to continue to debug and improve it 🤗</h3>
<p>So if you have feedback, please go to https://spectrum.utile.space and on the top right, there’s a link to submit feedback through a google form</p>
]]></content:encoded></item><item><title><![CDATA[A better way to discuss?]]></title><description><![CDATA[Cover picture source: https://www.youtube.com/watch?v=_0ysPb44C28

First of all, welcome inside this new awesome rabbit hole I found which is Street Epistemology and today in that new article we’re going through Spectrum.
🧠 What is a Spectrum?
A spe...]]></description><link>https://sonny.alvesdi.as/a-better-way-to-discuss</link><guid isPermaLink="true">https://sonny.alvesdi.as/a-better-way-to-discuss</guid><category><![CDATA[street-epistemology]]></category><category><![CDATA[debate]]></category><category><![CDATA[conversations]]></category><category><![CDATA[growing]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Tue, 01 Jul 2025 02:13:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751335653954/a07aa07d-a3e0-42e0-a6e9-245a001862ad.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>Cover picture source:</em> <a target="_blank" href="https://www.youtube.com/watch?v=_0ysPb44C28"><em>https://www.youtube.com/watch?v=_0ysPb44C28</em></a></p>
</blockquote>
<p>First of all, welcome inside this new awesome rabbit hole I found which is Street Epistemology and today in that new article we’re going through Spectrum.</p>
<h1 id="heading-what-is-a-spectrum">🧠 What is a Spectrum?</h1>
<p>A spectrum is an adaptation of Street Epistemology, a technique rooted in the Socratic method that uses thoughtful questioning to examine the foundations of one's beliefs. In a spectrum, participants physically position themselves along a spectrum line to indicate their level of agreement or disagreement with a given statement. This visual representation facilitates open dialogue and helps individuals understand the diversity of perspectives on complex issues.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751335781302/d7d0eb51-073d-4c8b-bee2-13d20abcd605.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-objectives-of-a-spectrum">🎯 Objectives of a Spectrum</h2>
<ul>
<li><p>Encourage critical thinking and self-reflection on personal belief.</p>
</li>
<li><p>Foster respectful and meaningful conversations among individuals with differing viewpoint.</p>
</li>
<li><p>Develop skills in active listening and constructive dialogue.</p>
</li>
<li><p>Promote understanding and empathy through shared exploration of idea.</p>
</li>
</ul>
<h2 id="heading-how-it-works">🛠️ How It Works</h2>
<ol>
<li><p><strong>Statement Presentation</strong>: A facilitator introduces a thought-provoking statement for discussion.</p>
</li>
<li><p><strong>Physical Positioning</strong>: Participants stand along a spectrum line that represents a range of agreement or disagreement with the statement.</p>
</li>
<li><p><strong>Dialogue and Exploration</strong>: Through guided questions and discussions, participants share their reasoning, challenge assumptions, and consider alternative viewpoints.</p>
</li>
<li><p><strong>Reflection and Adjustment</strong>: As the conversation progresses, individuals may choose to adjust their position on the spectrum, reflecting a shift in their perspective based on the dialogue.</p>
</li>
</ol>
<h2 id="heading-consideration">⚠️ Consideration</h2>
<p>Engaging in a Spectrum requires a willingness to openly express one's beliefs and to respectfully consider differing opinions. Participants should be prepared for the possibility of standing alone in their viewpoint and should feel comfortable with public discourse.</p>
<p>For a practical demonstration of a Spectrum, you can watch the following video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=TjWYUv3QqZo">https://www.youtube.com/watch?v=TjWYUv3QqZo</a></div>
]]></content:encoded></item><item><title><![CDATA[Modern dependency management]]></title><description><![CDATA[One of the greatest tool available on GitHub is Dependabot. For those not familiar with it, in short it's a bot reviewing your list of dependencies and proposing PRs to update them.
https://docs.github.com/en/code-security/getting-started/dependabot-...]]></description><link>https://sonny.alvesdi.as/modern-dependency-management</link><guid isPermaLink="true">https://sonny.alvesdi.as/modern-dependency-management</guid><category><![CDATA[dependabot]]></category><category><![CDATA[dependency management]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Software Testing]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Fri, 14 Mar 2025 15:14:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/T9rKvI3N0NM/upload/65a596f93f08289d0cea818d89e10d2a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the greatest tool available on GitHub is Dependabot. For those not familiar with it, in short it's a bot reviewing your list of dependencies and proposing PRs to update them.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide">https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide</a></div>
<p> </p>
<p>If you are not using GitHub there are alternatives including the open source version of Dependabot (<a target="_blank" href="https://github.com/dependabot">https://github.com/dependabot</a>) or also Renovate: https://www.mend.io/renovate/</p>
<p>But in this article I will not go through the configuration of any of them. I wanted to share my experience. I have been using for Dependabot for a couple of years now and I think the following advice should apply to any equivalent alternatives.</p>
<ul>
<li><p>Never merge any Dependabot’s PRs right away!</p>
</li>
<li><p>It’s tempting but we should check a few things before.</p>
</li>
<li><p>First of all you need a CI workflow that will run on every PR push. And you should check whether it did run successfully or not.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741963732145/b789eb8f-db54-4fb0-91d5-bc1d2fa1f428.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>That workflow I suggest to be at least checking <strong>formatting</strong>, <strong>linting</strong>, and confirm <strong>build</strong>/compiling still works. Ideally we have <strong>tests</strong> too.</p>
<ul>
<li>You can find an example for a Svelte front-end here: <a target="_blank" href="https://github.com/SonnyAD/utile-front/blob/main/.github/workflows/pr.yml">https://github.com/SonnyAD/utile-front/blob/main/.github/workflows/pr.yml</a></li>
</ul>
</li>
<li><p><strong>In the case the PR did not pass,</strong> pretty often (from my experience) it's a minor thing to fix/migrate. Generally you can see from the lint or build errors what is not compiling anymore. So checkout the branch of the PR locally do the fix yourself in the branch and commit/push, once the PR workflow passes then you can consider merging it.</p>
</li>
<li><p><strong>In the rare case where things need a huge migration</strong>, I suggest considering to delay that migration until you have proper time and focus for it. Or you can just decide to stick to the current version. For the latter, you can add something like below in the <code>dependabot.yaml</code>. The example makes Dependabot stick with any 20.x.y version for <code>@types/node</code>:</p>
</li>
</ul>
<pre><code class="lang-yaml">    <span class="hljs-attr">ignore:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">dependency-name:</span> <span class="hljs-string">'@types/node'</span>
        <span class="hljs-attr">versions:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">'&gt;=21.0.0'</span>
</code></pre>
<ul>
<li>After merging, in some cases, especially if you don't have much test coverage, an update can bring an unwanted behavior that you notice later. At that moment, don't hesitate to come back to the merged PR, and click on the Revert button in it and merge right away the reverting changes</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741964266752/8802316a-c227-49d5-93c4-fdb49ee8cb60.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-final-pieces-of-advice">Final pieces of advice</h3>
<p>Generally it's better to stay on latest versions of your dependencies. Because they likely have less bugs, are more performant, have up-to-date documentation (not always true), etc.</p>
<p>But you don't need to rush updates too.</p>
<p>Plan regular time to process the dependabot PRs. And better update dependencies days ahead of releases (if you don’t apply CD and/or don’t have enough tests) because of the unwanted behavior we can notice sometimes later.</p>
<p>Updating dependencies is an ongoing (never-ending) maintenance work. But I believe that if you apply all the advice, it will make your products last longer too.</p>
]]></content:encoded></item><item><title><![CDATA[Street Epistemology]]></title><description><![CDATA[Photo by Harli Marten on Unsplash

As long as I remember I have always been interested by skepticism. And I think one element that really resonated with me has been that conference talk by Phil Plait:
https://www.youtube.com/watch?v=FrFRbGjUtJk
 
15 ...]]></description><link>https://sonny.alvesdi.as/street-epistemology</link><guid isPermaLink="true">https://sonny.alvesdi.as/street-epistemology</guid><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 03 Mar 2025 02:24:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740986483832/5c46ca14-6ddc-4987-b40f-b87b5248a8b9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Photo by <a target="_blank" href="https://unsplash.com/@harlimarten?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Harli Marten</a> <a target="_blank" href="https://unsplash.com/@harlimarten?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">on Unsplash</a></p>
</blockquote>
<p>As long as I remember I have always been interested by skepticism. And I think one element that really resonated with me has been that conference talk by Phil Plait:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=FrFRbGjUtJk">https://www.youtube.com/watch?v=FrFRbGjUtJk</a></div>
<p> </p>
<p>15 years later I would still recommend a watch today.</p>
<p>I think that motto: “Don’t be a dick” stayed with me ever since. It was not easy while spending time on Twitter. I have probably been a dick several times over there. And I only remember one and only one good interaction on Twitter. I believe it was because my interlocutor at that time really tried to understand me, and I was giving him the same treatment.</p>
<h2 id="heading-what-is-this-blog-about">What is this blog about?</h2>
<p>“Street Epistemology” (SE), it’s only after hearing at least dozens of times about the concept that I decided to investigate. At that time, the reference everybody was pointing at was the videos from Anthony Magnabosco.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=LmCujhOfazY">https://www.youtube.com/watch?v=LmCujhOfazY</a></div>
<p> </p>
<p>At first I didn’t like his videos TBH. The topic is often about religion which is not my cup of tea. But after retrying a couple of times, I started to notice how easily Anthony could speak of tough subjects like religious belief with anybody on the street. And that without an ounce of conflict, all in peace. Without being a dick…</p>
<h2 id="heading-so-what-is-street-epistemology">So what is Street Epistemology?</h2>
<p>It is a set of techniques and a practice to conduct a pleasant conversation with someone while discussing some of his important beliefs. The conversation is asymmetric, each side plays a specific role.</p>
<blockquote>
<h3 id="heading-the-roles">The roles</h3>
<h4 id="heading-the-questioner"><strong>The « questioner »</strong></h4>
<p>The "questioner" guides the conversation. Their first goal is to create a calm and welcoming space where their partner feels safe expressing their deeply held beliefs. Without this, SE is impossible!</p>
<p>The second goal is to understand their partner’s ideas by asking step-by-step questions. Success is achieved when the questioner can summarize the other person’s thoughts as clearly as if they were their own.</p>
<p>Finally, the questioner’s last goal is to provide critical perspective. They help their partner articulate their ideas, reflect on their statements, and even strengthen their arguments. There is no notion of winning or losing—regardless of the outcome, both parties benefit.</p>
<h4 id="heading-the-interlocutor"><strong>The « interlocutor »</strong></h4>
<p>As for the interlocutor, they express their opinion. Around 70% of the speaking time is dedicated to them, and only their perspective is discussed—the questioner’s opinion is discouraged. If the interlocutor asks for the questioner’s view, it should be shared only at the end of the conversation. This approach helps prevent much of the tension.</p>
<h3 id="heading-the-five-steps-of-an-se-conversation">The Five Steps of an SE conversation</h3>
<h4 id="heading-building-rapport"><strong>Building Rapport</strong></h4>
<p>Establishing a friendly connection usually takes less than five minutes. Rushing straight to the point to save time would be a mistake—genuine interest in the other person, sharing personal experiences, and finding common ground are valuable. This time is essential for fostering self-reflective thinking while making the conversation both productive and enjoyable.</p>
<p>Consent to discuss a sensitive topic must always be obtained explicitly, even with close acquaintances. Pressuring someone, even unintentionally, undermines trust. Maintaining a positive atmosphere is crucial—if consent wavers or the mood deteriorates, it should be addressed immediately.</p>
<h4 id="heading-focusing-on-the-key-argument"><strong>Focusing on the Key Argument</strong></h4>
<p>This process consists of three steps. Initially, the topic may be vaguely defined, so some time is spent refining a statement that truly reflects the interlocutor’s core belief. Next, the arguments supporting this belief are listed. Finally, the key argument—the one carrying the most weight for the interlocutor—is identified.</p>
<h4 id="heading-identifying-the-epistemology"><strong>Identifying the Epistemology</strong></h4>
<p>This step involves clarifying the process or method the interlocutor uses to support their key argument. It may be based on personal experience, an authoritative source, scientific consensus, tradition, intuition, faith, or other reasoning.</p>
<h4 id="heading-testing-the-epistemology"><strong>Testing the Epistemology</strong></h4>
<p>This is the most delicate phase, as the goal is not to counter-argue but to help the interlocutor find their own counter-arguments. They are encouraged to consider questions they may not have asked before: <em>Are my ideas internally consistent? How could my belief be proven wrong? In what situations? Using what methods?</em></p>
<p>An experienced questioner guides the interlocutor toward such reflections without imposing their own views. It is not uncommon for the questioner to change their own perspective based on the discussion. The most rewarding moments are often marked by long, thoughtful silences, followed by <em>“That’s a good question”</em> or <em>“I don’t know.”</em></p>
<h4 id="heading-conclusion"><strong>Conclusion</strong></h4>
<p>An SE conversation can be mentally demanding for both participants. When possible, the questioner aims to conclude on a positive note, even if not all objectives are met.</p>
<p>Paradoxically, while changing one’s mind takes time, the best conversations last under twenty minutes, often leaving a sense of unfinished business. The goal is to spark deep reflection over several days, until the next discussion. Moreover, concluding an interview does not mean closing the conversation—the questioner remains available to share and challenge their own beliefs, at least as an act of reciprocity.</p>
</blockquote>
<p><em>Source: Jason Bloch, Tanguy Robyr, and Charlie Tétillon from the non-profit organization “Opinion sur Rue” promoting SE in French</em></p>
<h2 id="heading-how-to-learn-and-practice-it">How to learn and practice it</h2>
<p>So aside obviously the resources I already mentioned, now in 2025 I would recommend:</p>
<ul>
<li><p>The book “<em>How to Have Impossible Conversations”</em> from Peter Boghossian. He is an American philosopher and college professor. And he is the main person who developed <em>Street Epistemology</em> methodology during the 2000s through field experiments and academic research. He refined his method by incorporating insights from psychology, negotiation, and deradicalization. His book from 2019 remains the key reference on the method.</p>
<p>  <img src="https://m.media-amazon.com/images/I/41cZ3Gf6O0L._SY445_SX342_.jpg" alt="How to Have Impossible Conversations: A Very Practical Guide" class="image--center mx-auto" /></p>
</li>
<li><p>The free online course from Street Epistemology International non-profit organization led by Anthony Magnabosco:<br />  <a target="_blank" href="https://navigatingbeliefs.com/">https://navigatingbeliefs.com/</a></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740925428573/8e04f976-4047-437f-a400-d4eb9af235fd.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>But if you are a French speaker,</strong> I would <strong>strongly</strong> <strong>recommend</strong> the free 9 weeks training from the non-profit French organization called “<strong>Opinions sur Rue</strong>” <a target="_blank" href="https://www.opinions-sur-rue.fr/">https://www.opinions-sur-rue.fr/</a><br />  I had the chance to take their training in 2024 and it was great. Also their Discord community is pretty active and easy-going.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740925537962/ecc50e0e-d700-4dc1-997a-946c71fdb926.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h2 id="heading-but-why-am-i-talking-about-se-on-a-blog-mostly-about-software-engineering">But why am I talking about SE on a blog mostly about software engineering?</h2>
<p>Well, for many reasons.</p>
<p>Polarization on social networks and in our modern society is a big problem. And us software engineers are part of the problem, and part of the solution too. So I believe there is inspiration to take from a tool like Street Epistemology and to apply to our software to help understanding each other and improving the search of consensual solutions instead of division.</p>
<p>As an engineering manager as well, we all run 1 on 1 meetings with our collaborators. And I think there are few things from SE that we should also use as well:</p>
<ol>
<li><p>Embrace silences. We tend to avoid silence, thinking time is money and that we should make the most of the meeting time but just don’t do that. Silences are an important to leave room for thinking things through.</p>
</li>
<li><p>Use active listening. Let your collaborator express himself, your main goal during these 1 on 1 is to understand what you can do to help him/her. So you need to hear him/her and check if you really understood him/her by rephrasing his/her thoughts.</p>
</li>
</ol>
<p>One last thing: Spectrum.<br />Spectrum is a derived practice from Street Epistemology also from Peter Boghossian, where multiples person participate to a conversation about their belief on a specific claim and standing physically on a paper representing their position from Strongly Agree to Strongly Disagree.</p>
<p>In a spirit of contributing to the movement of SE for better discussing on the Internet, I started to develop an online tool to run a Spectrum online. The team at “Opinion sur Rue” has been using it for some time now. And I want to share more details about it in future blog articles. So stay tuned.</p>
]]></content:encoded></item><item><title><![CDATA[How to compute Pi (or Tau) in Go]]></title><description><![CDATA[As I mentioned in my first article about utile.space, I was interesting to do some math.
https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services
 
Ok so, how to compute Pi?
We are in 2024, so the first thing I did is to ask our favori...]]></description><link>https://sonny.alvesdi.as/how-to-compute-pi-or-tau-in-go</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-compute-pi-or-tau-in-go</guid><category><![CDATA[Tau]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[pi]]></category><category><![CDATA[hobby]]></category><category><![CDATA[Mathematics]]></category><category><![CDATA[llm]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 16 Sep 2024 06:02:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zIWF3xoHR3w/upload/bfdffd6b4f5d395a4e62f6d957785ab5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As I mentioned in my first article about <a target="_blank" href="https://utile.space">utile.space</a>, I was interesting to do some math.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services">https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services</a></div>
<p> </p>
<h2 id="heading-ok-so-how-to-compute-pi">Ok so, how to compute Pi?</h2>
<p>We are in 2024, so the first thing I did is to ask our favorites LLMs to help me with the code.</p>
<p>I tried ChatGPT, Claude, and some others… They all provided me an algorithm… that was not working. And even trying to debug the algorithms with them by reporting errors and such. It was a dead end…</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExcTRianBtMXowbjRnODVkdnJ2NWMxdDRrbDBvb3h5azBydWQ1djlwNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/nTfdeBvfgzV26zjoFP/giphy.gif" alt class="image--center mx-auto" /></p>
<p>Then I went on Google, I didn’t find anything precisely in Go. So I think we can assume the LLMs were trained on the same data that is not containing a solution for that. Hence they were hallucinating an algorithm mixed on others solution and Go code they learnt.</p>
<h2 id="heading-no-llms-then-lets-use-human-intelligence">No LLMs then! Let’s use Human Intelligence…</h2>
<p>After reading the wikipedia page of Pi, one of the algorithm mentioned to compute Pi is called Chudnovsky Algorithm.</p>
<p>I am not going into the explanation of the algorithm here, so if you want more details I invite you to check out the wikipedia page about it:</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Chudnovsky_algorithm">https://en.wikipedia.org/wiki/Chudnovsky_algorithm</a></p>
<p>The good thing here is that the page provides a Python code to compute it! So now I just need to convert that code to Go!</p>
<h2 id="heading-converting-python-code-to-go-code">Converting Python code to Go code</h2>
<p>To be honest, I tried again LLMs at that stage to see if they could help…</p>
<p>They were of no help again… except one thing. Thanks to ChatGPT I learnt that the sort of equivalent of the <code>decimal</code> module of Python in Go is <code>math/big</code>.</p>
<p>From now I took the simplest approach to reach my goal: I copy pasted the Python code and converted by hand to Go line by line.</p>
<p>About 20 lines of Python code and mostly math calculation so it’s not that long and complex.</p>
<p>We have a <code>chudnovsky</code> function that takes one argument <code>n</code> which will stop the convergence to Pi. Again this is the formula from Chudnovsky below.</p>
<p>$$\pi =\lim _{n\to \infty }{\frac {426880{\sqrt {10005}}\cdot Q(1,n)}{13591409Q(1,n)+R(1,n)}}$$</p><p>Inside the <code>chudnovsky</code> function we then call the recursive function <code>binarySplit</code>.</p>
<h2 id="heading-challenges-of-the-conversion">Challenges of the conversion</h2>
<p>The first major difference with Python I encountered has been that Golang does not provide operator overloading. So while in Python is pretty clean using <code>*</code> and <code>/</code> it was not possible with Go and the package <code>math/big</code>.</p>
<p>For instance <code>*</code> has to be replaced by a call to <a target="_blank" href="https://pkg.go.dev/math/big#Float.Mul">.Mul(x, y)</a> and <code>+</code> by <a target="_blank" href="https://pkg.go.dev/math/big#Float.Add">.Add(x, y)</a>.</p>
<p>Two others operators in Python gave me a bit of trouble.</p>
<h3 id="heading-cube">Cube</h3>
<p>In Python the line is:</p>
<pre><code class="lang-python">Qab = <span class="hljs-number">10939058860032000</span> * a**<span class="hljs-number">3</span>
</code></pre>
<p>Looking at the <code>math/big</code> <a target="_blank" href="https://pkg.go.dev/math/big#Float">https://pkg.go.dev/math/big#Float</a> I didn’t see any Power function. So I ended writing this simple version of a Cube function for this type:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">cube</span><span class="hljs-params">(v *big.Float)</span> *<span class="hljs-title">big</span>.<span class="hljs-title">Float</span></span> {
    result := newBigFloat(<span class="hljs-number">1</span>)
    result.Mul(result, v)
    result.Mul(result, v)
    result.Mul(result, v)
    <span class="hljs-keyword">return</span> result
}
</code></pre>
<p>If it would have not been a power of 3, I would have probably written a loop. But here I believe this is clear and simple enough. Most important it does the job!</p>
<h3 id="heading-floor-division">Floor division</h3>
<p>In Python the line is:</p>
<pre><code class="lang-python">m = (a + b) // <span class="hljs-number">2</span>
</code></pre>
<p>I didn’t know about this operator, and it exists in some others languages. You can find the details here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.geeksforgeeks.org/floor-division-in-python/">https://www.geeksforgeeks.org/floor-division-in-python/</a></div>
<p> </p>
<p>But in two words, as its name says, it divides a by b and then floor the result. So in an other word, it’s a Euclidean division.</p>
<p>The good thing here is that as long as my numerator and denominator are integer in Go, the classic <code>/</code> operator is a Euclidean division in Go.</p>
<p>So the conversion simply became:</p>
<pre><code class="lang-go">m := (a + b) / <span class="hljs-number">2</span>
</code></pre>
<h2 id="heading-after-that-i-noticed-something-was-off">After that, I noticed something was off</h2>
<p>For the moment, I disregarded the Python line:</p>
<pre><code class="lang-python">decimal.getcontext().prec = <span class="hljs-number">100</span> <span class="hljs-comment"># number of digits of decimal precision</span>
</code></pre>
<p>This is a convenient way in Python to change the precision of the big float you are manipulating.<br />And after reading the big.Float from Go, I noticed that by default they only 53 digits of precision:</p>
<blockquote>
<p>NewFloat allocates and returns a new <a target="_blank" href="https://pkg.go.dev/math/big#Float">Float</a> set to x, with precision 53 and rounding mode <a target="_blank" href="https://pkg.go.dev/math/big#ToNearestEven">ToNearestEven</a>.</p>
</blockquote>
<p>So while I am trying to compute a result of at least 10K decimals, using something with only 53 digits is pretty pointless…</p>
<p>Another annoying thing is there is no one-liner like Python. So I came up with a factory to create my big.Float with the right precision set in advance.</p>
<pre><code class="lang-python">func newBigFloat(v float64) *big.Float {
    <span class="hljs-keyword">return</span> big.NewFloat(v).SetPrec(floatPrecision)
}
</code></pre>
<p>All the pieces of the puzzle were now more or less complete now!</p>
<h2 id="heading-and-then-pi">And then Pi!</h2>
<pre><code class="lang-go"><span class="hljs-number">3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375679</span>
</code></pre>
<p>Here is Pi up to 10K decimals, that you can get here too: <a target="_blank" href="https://utile.space/math">https://utile.space/math</a></p>
<p>It’s computed dynamically each time. 10K is the reasonable of digits that my server can compute in a reasonable time.</p>
<h1 id="heading-for-the-fun-i-computed-1m-decimals-too">For the fun, I computed 1M decimals too</h1>
<p>As just I said, 10K is somehow the limit of my server, but I wanted to go bigger.</p>
<p>I chose to run the computation locally on my computer, with enough precision and let the thing run for 10-15 minutes. Then saved the result in a file.</p>
<p>Thanks to it, you can also access of the first 1M on utile.space by clicking on <code>Lazy load π 1M first decimals</code>.</p>
<p>Technically via a pagination system, you will browse that file I computed on my computer to read the 1M in your browser page by page. IIRC 10K decimals per page.</p>
<p>I didn’t realize before but 1M digits it’s very long…</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExaXh5aTRhbml2ajNuaXc3NWpnczZ2enJoNTEydGdwbnplcDd0aGl4dyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/26ufdipQqU2lhNA4g/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-hey-wait-what-about-tau">Hey wait! What about Tau?</h2>
<p>Yeah, right! If you don’t know about Tau I invite you to read the Tau manifesto first!</p>
<p>Here: <a target="_blank" href="https://utile.space/pdf/tau-manifesto.pdf">https://utile.space/pdf/tau-manifesto.pdf</a></p>
<p>In shorts, the main idea is that we often need <code>2*Pi</code> , not Pi itself. So instead let’s use Tau which is equal to <code>2*Pi</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726465436996/764459db-8dd6-4d1e-8778-a15643d00282.png" alt class="image--center mx-auto" /></p>
<p>One Tau radians angle is a full circle. Half of Tau of Half a circle.</p>
<p>A bit more logical, isn’t it?</p>
<p>And for the code for it I used the most simple and readable one:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ChudnovskyTau</span><span class="hljs-params">(n <span class="hljs-keyword">int</span>)</span> *<span class="hljs-title">big</span>.<span class="hljs-title">Float</span></span> {
    pi := Chudnovsky(n)
    pi.Mul(pi, newBigFloat(<span class="hljs-number">2.0</span>))

    <span class="hljs-keyword">return</span> pi
}
</code></pre>
<h3 id="heading-conclusion-whats-next">Conclusion, what’s next?</h3>
<p>What I retained personally from the experience:</p>
<ul>
<li><p>It demonstrates again that (current) LLMs are a mirror of the current knowledge available on internet</p>
<ul>
<li>I haven’t tried the latest LLMs designed towards reflection and construction of a train of thoughts. I might have some surprise with it.</li>
</ul>
</li>
<li><p>I got to know the <code>math/big</code> package in Go.</p>
</li>
<li><p>I also implemented a websocket server for the purpose of serving the 1M digits of Pi in lazy loading fashion. That websocket that I am going to experience more and more with to create interactive experience.</p>
</li>
</ul>
<p>What’s next? Well the Chudnovsky algorithm I have is single-threaded. From my understanding there are possibilities of parallelizing some of the computation, likely here:</p>
<pre><code class="lang-go">Pam, Qam, Ram := binarySplit(a, m) <span class="hljs-comment">// on one thread</span>
Pmb, Qmb, Rmb := binarySplit(m, b) <span class="hljs-comment">// on another</span>
</code></pre>
<p>So I might come back to that later. I might also try to compute more digits. To server 10M, 100M, 1B digits of Pi. But not sure yet. Because it represents challenges in terms of size 1B represents 1G and computation time.</p>
]]></content:encoded></item><item><title><![CDATA[How to fail at documenting your project...]]></title><description><![CDATA[In July 2021, I was happily introducing in an article the v0.0.1 of my hobby project: utile.space, a Swiss army knife services website.
https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services-part-2
 
At the end of the blog, I was pro...]]></description><link>https://sonny.alvesdi.as/how-to-fail-at-documenting-your-project</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-fail-at-documenting-your-project</guid><category><![CDATA[Blogging]]></category><category><![CDATA[#failing]]></category><category><![CDATA[Dart]]></category><category><![CDATA[documentingmyjourney]]></category><category><![CDATA[projects]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 02 Sep 2024 14:20:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/cdMAU_x9mxY/upload/2e0919c758346c19323e40d4eb8d139b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In July 2021, I was happily introducing in an article the <em>v0.0.1</em> of my hobby project: <a target="_blank" href="https://utile.space">utile.space</a>, a Swiss army knife services website.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services-part-2">https://sonny.alvesdi.as/building-my-personal-swiss-army-knife-services-part-2</a></div>
<p> </p>
<p>At the end of the blog, I was promising to follow up and describing my journey... Today September 2nd, 2024, the website is now at its version 4.5.0....</p>
<p>So we can fairly say that I failed at documenting that project.</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExb2VtdmVzcWN1dHU4czZoOWQyemY4dHFrZGg5ZjhmOGZpeDkxdmEyciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/y9gcCOXpNX8UfZrp0X/giphy.gif" alt class="image--center mx-auto" /></p>
<p>Let's be honest I <s>probably</s> over promised...</p>
<p>I tend to be curious and try a lot of things as you probably guessed when going through my blog. So between work, hobbies, family, and more, blogging was always at the bottom of my todo list.</p>
<p>Let's try to repair the situation!</p>
<p>Even if, I need to say it's truly a pity. Because I did face some challenges on my way that I think would have been interesting to share.</p>
<blockquote>
<p>For example, I started my front-end with Dart but I quickly gave up. It was three years ago so my memory around that decision is not that fresh. But IIRC I reached a dead-end where I was lacking something to help me binding values between my UI and my view models. I briefly started to build something alike <a target="_blank" href="https://angulardart.xyz/">Angular Dart</a>... And quickly felt like I was rewriting the wheel.<br />I took a step back and decided to give up on Dart.</p>
</blockquote>
<p>Anyway, let's just break the spell and I won't over promise or promise anything at all. I just hope I can share some interesting stuff to you in the <s>near </s> future.</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExaG1neTJramYxc2ZuNjlxMDFrMW9rMnY4Z3FldTFmeTZ1NXBseXRuNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/YnGDmAudv7F2UASBqK/giphy.gif" alt class="image--center mx-auto" /></p>
<p>For the curious ones, my website link: https://utile.space and the GitHub repos: https://github.com/SonnyAD/utile-compose</p>
]]></content:encoded></item><item><title><![CDATA[How to enter the gaming industry?]]></title><description><![CDATA[I held a conference to introduce the different careers inside the gaming industry to high school students, and that presentation is a summary of it.

ℹ️ This blog article is for you if you are willing to work in the video game industry, but you are n...]]></description><link>https://sonny.alvesdi.as/how-to-enter-the-gaming-industry</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-enter-the-gaming-industry</guid><category><![CDATA[Career]]></category><category><![CDATA[Video Games Industry ]]></category><category><![CDATA[Video games]]></category><category><![CDATA[High School]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Sun, 09 Jun 2024 14:38:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/auf3GwpVaOM/upload/1cc89c0810d2c92feace35660f72e31e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I held a conference to introduce the different careers inside the gaming industry to high school students, and that presentation is a summary of it.</p>
</blockquote>
<p><mark>ℹ️ This blog article is for you if you are willing to work in the video game industry, but you are not sure how yet.</mark></p>
<hr />
<h2 id="heading-who-am-i">Who am I?</h2>
<p>Sonny Alves Dias</p>
<ul>
<li><p>🖥 <strong>Software engineer</strong><br />  Master's degree from l'Université de Technologie de Belfort-Montbéliard in France</p>
</li>
<li><p>🕹 <strong>10 years in the video game industry</strong><br />  Mostly doing development and production of video games</p>
</li>
<li><p>🇨🇳 <strong>9 years in China</strong><br />  Shanghai and Guangzhou</p>
</li>
<li><p>🛠️ <strong>Skills</strong><br />  Web, Unity, DevOps, Backend, IA</p>
</li>
</ul>
<hr />
<h1 id="heading-foreword">Foreword</h1>
<p>The gaming industry is composed of multiple company types including:</p>
<ul>
<li><p><strong>Individuals</strong> : Jonathan Blow, Lukas Pope, ...</p>
</li>
<li><p><strong>SMEs</strong> : Motion Twins, Hello Games, Asobo Studio, ...</p>
</li>
<li><p>Up to <strong>big companies</strong> and <strong>multinational groups</strong> : Don't Nod, Ubisoft, Nintendo, ...</p>
</li>
</ul>
<p>In the latter ones, you will have a specific job role and work on your expertise. While in SMEs, you will have multiple job roles and work on your versatility.</p>
<hr />
<h1 id="heading-some-definitions">Some definitions</h1>
<ul>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Visual_effects">Visual Effects (VFX)</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Sound_effect">Sound Effects (SFX)</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/User_interface">User Interface (UI)</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/User_experience">User Experience (UX)</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Game_testing">Quality Assurance (QA)</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Game_engine">Game engine</a></p>
</li>
</ul>
<hr />
<h1 id="heading-specialties-list">Specialties List</h1>
<p>A) Graphics<br />B) Audio<br />C) Technical<br />D) Marketing<br />E) Test / QA<br />F) Localization<br />G) Production<br />H) Design<br />I) Support</p>
<hr />
<h2 id="heading-a-graphics">A) Graphics</h2>
<hr />
<h3 id="heading-graphic-artist">Graphic artist</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717939275418/9da87a3f-9fdd-40ab-9b45-2745f1c5425f.jpeg" alt class="image--center mx-auto" /></p>
<p>The graphic artist or illustrator in video games creates graphic elements to enhance the game's aesthetics, including characters and environments. Working with design teams, they use specialized software to bring their creations to life, contributing to the game's visual identity.</p>
<ul>
<li><p>Concept artist</p>
</li>
<li><p>Character designer</p>
</li>
<li><p>Environment artist</p>
</li>
<li><p>2D Games</p>
</li>
<li><p>Marketing</p>
</li>
</ul>
<hr />
<h3 id="heading-vfx-artist">VFX Artist</h3>
<p><a target="_blank" href="https://www.youtube.com/watch?v=_69al2qhozI"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717940782593/d8cb540d-c0c2-477d-9e43-f65f76a72320.jpeg" alt="Source CGHOW https://www.youtube.com/watch?v=_69al2qhozI" class="image--center mx-auto" /></a></p>
<p>The VFX artist in the video game industry is responsible for creating and implementing digital visual effects such as explosions, fire, and magical effects. By collaborating with development teams, they use specialized software to bring these elements to life, contributing to the game's immersive aesthetics.</p>
<hr />
<h3 id="heading-3d-modeler">3D Modeler</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717941211272/4b05f3a7-2f46-4488-a262-add784d0d2c2.jpeg" alt class="image--center mx-auto" /></p>
<p>The 3D modeler in video games creates three-dimensional models for characters, objects, and environments, contributing to visual quality and immersion. Using specialized software, they collaborate with development teams to build the game's virtual world.</p>
<hr />
<h3 id="heading-uiux-designer">UI/UX designer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717941514242/72a0bbbc-eada-42ac-923a-cba3e4f1f8fb.png" alt class="image--center mx-auto" /></p>
<p>The UI/UX designer in video games designs the user interface (UI) and user experience (UX). Their role is to create intuitive and aesthetic designs, collaborating with development teams to ensure a smooth and immersive gaming experience.</p>
<hr />
<h3 id="heading-animator">Animator</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942025398/3c4df1df-3d4e-4d04-9a7e-b5b90393b905.jpeg" alt class="image--center mx-auto" /></p>
<p>The animator in the video game industry is responsible for bringing characters, objects, and actions in the game to life by creating animations. Using specialized software, they contribute to the players' immersion in the virtual world. Their work is essential for creating visually dynamic and captivating gaming experiences.</p>
<hr />
<h3 id="heading-video-editor">Video Editor</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942065190/5f190658-e8f6-442c-8f0b-83e3881bad6d.jpeg" alt class="image--center mx-auto" /></p>
<p>The video editor in the video game industry is responsible for assembling and editing video sequences to create coherent and attractive content. In collaboration with production teams, they use editing software to structure the game's visual elements, including cinematic and trailers, ensuring a smooth and impactful visual narrative for players.</p>
<hr />
<h2 id="heading-b-audio">B) Audio</h2>
<hr />
<h3 id="heading-sfx-artist">SFX artist</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942495379/f0b02eb2-cb67-4f27-8834-e40c6119493e.jpeg" alt class="image--center mx-auto" /></p>
<p>Le SFX artiste dans le jeu vidéo crée et intègre les éléments sonores, tels que bruitages et musiques, pour améliorer l'expérience audio du jeu. En collaboration avec l'équipe de développement, ils utilisent des outils spécialisés pour donner vie aux mondes virtuels, contribuant ainsi à l'immersion des joueurs.</p>
<hr />
<h2 id="heading-c-technical">C) Technical</h2>
<hr />
<h3 id="heading-gameplay-programmer">Gameplay Programmer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942535602/e09d90c2-2044-42e0-bc13-9f27d4876c4a.png" alt class="image--center mx-auto" /></p>
<p>The gameplay programmer in the video game industry develops the code that governs the interaction and functionality of the gameplay. In collaboration with game designers, they translate ideas into lines of code, ensuring a smooth gaming experience that aligns with the game's vision.</p>
<hr />
<h3 id="heading-engine-programmer">Engine Programmer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942620914/b1d42c7a-f926-49ba-ab5b-60f89f199f97.jpeg" alt class="image--center mx-auto" /></p>
<p>The engine programmer in the video game industry focuses on developing the game engine, handling essential aspects such as graphics, physics, and performance optimization. In collaboration with development teams, they write code to improve the engine's efficiency and ensure a solid foundation for game creation.</p>
<hr />
<h3 id="heading-backendserver-programmer">Backend/Server Programmer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942649493/645d2de1-ed2b-4a30-9ea3-7708e0333912.jpeg" alt class="image--center mx-auto" /></p>
<p>The backend programmer in the video game industry develops the server logic and databases to ensure the functionality of online features. Working closely with development teams, they write code to manage server-client interactions, ensuring smooth and reliable multiplayer experiences.</p>
<hr />
<h3 id="heading-devops-engineer">DevOps Engineer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942684849/ab56cd85-a548-484d-b9a9-f27c500cb75c.png" alt class="image--center mx-auto" /></p>
<p>The DevOps engineer in the video game industry facilitates collaboration between development and operations teams. Their central role involves automating deployments, monitoring performance, and ensuring continuous integration. By optimizing operational efficiency, they help ensure the stability of game infrastructures for a smooth user experience.</p>
<hr />
<h3 id="heading-it-manager">IT manager</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942708654/7953ab2d-383e-4cef-a85b-d0bc3fe6b26c.jpeg" alt class="image--center mx-auto" /></p>
<p>The IT manager in the video game industry oversees IT operations, ensuring the security, availability, and efficiency of systems. In collaboration with teams, they define technology strategies, ensure project implementation, and contribute to the smooth functioning of the game's technological environment.</p>
<hr />
<h2 id="heading-d-marketing">D) Marketing</h2>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942753145/29e99429-e1c6-423d-9a66-241fa231cb3a.jpeg" alt class="image--center mx-auto" /></p>
<p>Marketing is responsible for promoting games to the target audience and maximizing their visibility in the market. Their mission involves developing effective marketing strategies, including advertising campaigns, promotional partnerships, and launch events. They work closely with development teams to identify the game's unique features and create compelling messages to attract players. The marketing department also analyzes market trends and player feedback to adjust promotional strategies and optimize business results. In summary, their goal is to raise awareness of the games and boost sales while strengthening the company's brand in the video game industry.</p>
<p>Here is a non-exhaustive list of jobs related to video game marketing.</p>
<ul>
<li><p>Marketing Director/CMO</p>
</li>
<li><p>PR relations</p>
</li>
<li><p>Social media manager</p>
</li>
<li><p>Community manager</p>
</li>
<li><p>Influencer/Content creator*</p>
</li>
<li><p>Writer and copy writer*</p>
</li>
</ul>
<hr />
<h2 id="heading-e-qa">E) QA</h2>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942780871/14a57a28-a6d7-4949-b16c-95fc4142811d.jpeg" alt class="image--center mx-auto" /></p>
<p>The QA (Quality Assurance) department in a video game development or publishing company is responsible for ensuring the quality and reliability of games before they are released to the market. Their mission involves thoroughly testing every aspect of the game to detect bugs, glitches, and performance issues. They conduct functional, compatibility, and localization tests to ensure the game is playable, stable, and suitable for different systems and languages. The QA department works closely with development teams to report identified issues and ensure they are resolved before the game is published. In summary, their goal is to guarantee a smooth and satisfying gaming experience for players.</p>
<p>Here is a non-exhaustive list of jobs related to video game marketing.</p>
<ul>
<li><p>Game tester</p>
</li>
<li><p>Localization tester</p>
</li>
<li><p>QA engineer</p>
</li>
</ul>
<hr />
<h2 id="heading-f-localisation">F) Localisation</h2>
<hr />
<h3 id="heading-chef-de-projet-localisation">Chef de projet localisation</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942807149/aa66b70f-f639-421d-859b-eb8e88cc936c.jpeg" alt class="image--center mx-auto" /></p>
<p>The localization project manager in video games coordinates the translation and linguistic adaptation of the game for different markets. By working with teams, they ensure the cultural and linguistic adaptation of the game, providing a consistent experience for a global audience.</p>
<hr />
<h2 id="heading-g-production">G) Production</h2>
<hr />
<h3 id="heading-producer">Producer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942828326/fb220c24-9483-4b1c-90d4-4a60d38b7636.jpeg" alt class="image--center mx-auto" /></p>
<p>The producer in the video game industry oversees the overall development of the game. Responsible for planning, coordinating, and monitoring the project, they work with development teams to ensure deadlines, budget, and creative vision are met. Their role is crucial in guaranteeing the quality and success of the game by effectively managing all production phases, from design to release.</p>
<hr />
<h2 id="heading-h-design">H) Design</h2>
<hr />
<h3 id="heading-game-designer">Game Designer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942854155/ccb6f004-145b-4394-bd7e-8cbab73d9a0b.jpeg" alt class="image--center mx-auto" /></p>
<p>Game design involves creating the rules, mechanics, and systems that define the gaming experience. Game designers envision the game's worlds, characters, and challenges, working with the development team to bring them to life using design tools. Their goal is to create engaging and balanced interactive experiences for players.</p>
<ul>
<li><p>Game Director</p>
</li>
<li><p>Game Designer</p>
</li>
<li><p>System Game Designer</p>
</li>
<li><p>Technical Game Designer</p>
</li>
</ul>
<hr />
<h3 id="heading-level-designer">Level Designer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942935640/eb4e81c4-de71-4224-a985-ac585417284b.jpeg" alt class="image--center mx-auto" /></p>
<p>The level designer creates the levels and playable environments in a video game, placing game elements to offer interesting challenges and an immersive experience for players.</p>
<hr />
<h3 id="heading-narrative-designer">Narrative Designer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717942980245/660ad114-3a8e-4abc-bbe0-5ecefe4b2279.jpeg" alt class="image--center mx-auto" /></p>
<p>The narrative designer creates the story, characters, and dialogues of a video game, seamlessly integrating them into the gameplay to provide an immersive narrative experience for players.</p>
<hr />
<h2 id="heading-i-support">I) Support</h2>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1717943014344/31a95eef-4520-410a-930c-bae33f53fbca.jpeg" alt class="image--center mx-auto" /></p>
<p>There are also, of course, several important roles that are common to all types of businesses and industries. Here is a non-exhaustive list below.</p>
<ul>
<li><p>Executive Assistant</p>
</li>
<li><p>Administrative Secretary</p>
</li>
<li><p>Legal Advisor, Lawyer</p>
</li>
<li><p>Human Resources Manager</p>
</li>
<li><p>Chief Financial Officer</p>
</li>
<li><p>Payroll Manager</p>
</li>
<li><p>etc.</p>
</li>
</ul>
<hr />
<h1 id="heading-some-advice">Some Advice</h1>
<ul>
<li><p>If you have a passion for video games, it's a good starter, but this is not enough!</p>
</li>
<li><p>Entering the industry can be difficult :</p>
<ul>
<li><p>A portfolio can greatly help you</p>
</li>
<li><p>An internship</p>
</li>
<li><p>Use your network</p>
</li>
</ul>
</li>
<li><p>Conditions inside the industry are improving but still pay attention to:</p>
<ul>
<li><p>Crunch problems</p>
</li>
<li><p>Sexism and any inclusion problems</p>
</li>
</ul>
</li>
<li><p>Being able to speak English is a must</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to do a (serverless) web redirection in AWS Route53?]]></title><description><![CDATA[Imagine you are using a DNS provider and you have a domain example.com and example.net redirecting to example.com. It's pretty easy to set up.
One day you migrate to AWS Route53 because you want geolocation, load balancing, or something of the sort. ...]]></description><link>https://sonny.alvesdi.as/how-to-do-a-serverless-web-redirection-in-aws-route53</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-do-a-serverless-web-redirection-in-aws-route53</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Devops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[route53]]></category><category><![CDATA[redirections]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Sat, 22 Apr 2023 14:54:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zF_pTLx_Dkg/upload/6374ad4a6ffb05e42ddb7facbba582bf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine you are using a DNS provider and you have a domain <a target="_blank" href="http://example.com">example.com</a> and <a target="_blank" href="http://example.net">example.net</a> redirecting to <a target="_blank" href="http://example.com">example.com</a>. It's pretty easy to set up.</p>
<p>One day you migrate to AWS Route53 because you want geolocation, load balancing, or something of the sort. And disaster! There is no web redirection.</p>
<p>With this article, you will know how to solve that and set up a serverless web redirection at a low cost and a little effort.</p>
<h1 id="heading-steps">Steps</h1>
<h2 id="heading-1-lambda">1. Lambda</h2>
<p>Please find below an example of a NodeJS lambda:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span>(event) =&gt; {
    <span class="hljs-keyword">const</span> res = {
        <span class="hljs-attr">statusCode</span>: <span class="hljs-number">301</span>,
         <span class="hljs-attr">headers</span>: {
            <span class="hljs-attr">Location</span>: <span class="hljs-string">'https://example.com'</span>
        }
    };
    <span class="hljs-keyword">return</span> res;
};
</code></pre>
<p>and Python</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>

    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">"statusCode"</span>: <span class="hljs-number">301</span>,
        <span class="hljs-string">"headers"</span>: {
            <span class="hljs-string">'Location'</span>: <span class="hljs-string">"https://example.com"</span>
        }
    }
</code></pre>
<h2 id="heading-2-api-gateway">2. API Gateway</h2>
<ul>
<li><p>Select a <code>REST API</code> (**not Private **)</p>
</li>
<li><p>In the next page,</p>
<ul>
<li><p>confirm <code>REST API</code>, not Websocket</p>
</li>
<li><p>create a <code>New API</code></p>
</li>
<li><p>give it a name like web-redirection</p>
</li>
<li><p>endpoint type select <code>Edge Optimized</code></p>
</li>
</ul>
</li>
<li><p>In the API detail page,</p>
<ul>
<li><p>Click on <code>Actions</code> and select <code>Create Method</code></p>
</li>
<li><p>Select <code>GET</code> method under the path / and confirm</p>
</li>
</ul>
</li>
<li><p>In the / GET method details,</p>
<ul>
<li>Select the lambda you created in the first section and save.</li>
</ul>
</li>
<li><p>Finally, publish the API by clicking on <code>Actions</code> &gt; <code>Deploy API</code></p>
<ul>
<li>Enter a stage name for your deployment something like <code>production</code></li>
</ul>
</li>
</ul>
<h2 id="heading-3-custom-domain-name">3. Custom Domain Name</h2>
<ul>
<li><p>Still in the API Gateway service, click on  <code>Custom Domain Names</code></p>
</li>
<li><p>For each domain you want to redirect, Create a Custom Domain Name</p>
<ul>
<li><p>Select <code>Edge Optimized</code> to match the API Gateway we created above</p>
</li>
<li><p>And select (or create) a certificate that matches the domain</p>
</li>
</ul>
</li>
<li><p>Once created, setup API mapping to the API gateway we created before with no path required</p>
</li>
</ul>
<h2 id="heading-4-cloudfront">4. CloudFront</h2>
<ul>
<li><p>Go to CloudFront and create a distribution</p>
</li>
<li><p>Do not define any alternate domain, and no certificate</p>
</li>
<li><p>For the origin enter the API gateway endpoint and specify for the origin path <code>/prod</code> as the stage name you defined earlier</p>
</li>
</ul>
<h2 id="heading-5-route53">5. Route53</h2>
<ul>
<li><p>Add a Route53 record on the domain</p>
</li>
<li><p>And point at the CloudFront from the previous section</p>
</li>
</ul>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Go to your domain <a target="_blank" href="http://example.net">example.net</a> and validate that the redirection to <a target="_blank" href="http://example.com">example.com</a> is working!</p>
]]></content:encoded></item><item><title><![CDATA[How to make a LÖVE WebGL build?]]></title><description><![CDATA[Since last article, I worked on these two planned features

Game Over screen with scoring and retry button
Finalizing the notes balancing and rhythm

But it’s not completely finalized yet, and will continue working on both. 
I thought though it would...]]></description><link>https://sonny.alvesdi.as/how-to-make-a-love-webgl-build-beathoven-devblog-2</link><guid isPermaLink="true">https://sonny.alvesdi.as/how-to-make-a-love-webgl-build-beathoven-devblog-2</guid><category><![CDATA[Game Development]]></category><category><![CDATA[Lua]]></category><category><![CDATA[love]]></category><category><![CDATA[Games]]></category><category><![CDATA[game]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Thu, 06 Oct 2022 03:51:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/JySoEnr-eOg/upload/b6c29105d3eb2b83737e0fb70df8f26d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since last article, I worked on these two planned features</p>
<ul>
<li>Game Over screen with scoring and retry button</li>
<li>Finalizing the notes balancing and rhythm</li>
</ul>
<p>But it’s not completely finalized yet, and will continue working on both. </p>
<p>I thought though it would be nice to make an article about building the game for WebGL and sharing a link to play the game in its current state! </p>
<h2 id="heading-how-to-make-a-webgl-build">🌐How to make a WebGL build?</h2>
<p>First, you need to install the tool from Davidobot: <a target="_blank" href="https://github.com/Davidobot/love.js">https://github.com/Davidobot/love.js</a></p>
<pre><code class="lang-bash">npm install -g love.js
</code></pre>
<h3 id="heading-web-server-with-proper-headers">Web server with proper headers</h3>
<p>Then you will need a server and a web server running on it. On my end, I use Nginx, and this is how I configured my <code>location</code>: </p>
<pre><code class="lang-erlang">location /beathoven/ {
        add_header Cross-Origin-Opener-Policy same-origin;
        add_header Cross-Origin-Embedder-Policy require-corp;
        alias /usr/share/nginx/html/beathoven/;
}
</code></pre>
<h3 id="heading-add-missing-mime-type">Add missing mime type</h3>
<p>After several tries looking at errors in browser, I realize also I needed to edit the file <code>/etc/nginx/mime.types</code> to add the definition for wasm file:</p>
<pre><code class="lang-erlang">    application/vnd.google-earth.kmz      kmz;
    application/wasm                      wasm;
    application/x-<span class="hljs-number">7</span>z-compressed           <span class="hljs-number">7</span>z;
</code></pre>
<h3 id="heading-use-7zip-not-tar-on-windows">Use 7zip not tar on Windows</h3>
<p>To package your game into a love file, you need to simply zip the files. </p>
<p>And since Windows 10, it includes a <code>tar</code> command line utility that you can use to make zip in scripts. But it looks like it’s not supported by the WebGL build. So I switched to 7Zip using the following parameters:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665027812714/ekWI08TXe.png" alt="Untitled.png" /></p>
<p>You can also use 7zip in command line.</p>
<h3 id="heading-my-build-amp-deploy-script">My Build &amp; Deploy script</h3>
<p>And this is what I ended up with to build and deploy my game on demand:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

tools/7za a -tzip Beathoven.zip assets/ gameobjects/ pages/ responsive/ utils/ fonts.lua main.lua -mx0
mv Beathoven.zip Beathoven.love

love.js -t Beathoven -c Beathoven.love game 

ssh server rm -rf /usr/share/nginx/html/beathoven/*

scp -r game/* server:/usr/share/nginx/html/beathoven/
</code></pre>
<h2 id="heading-where-to-test-the-game">🎮 Where to test the game:</h2>
<p>Now that I am able to build and deploy the game, here is the link to test it:
<a target="_blank" href="https://utile.space/beathoven/">https://utile.space/beathoven/</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Don't hesitate to give feedback on the game in the comments. Or let me know if you would like to give a hand. </p>
<p>Next steps are going to finalize the retry function of the game, which I started a big refactor for it. And I want to improve the UI then with animations and such. </p>
]]></content:encoded></item><item><title><![CDATA[Developing a rhythm game with LÖVE]]></title><description><![CDATA[Last week at the end of that article I mentioned that I was working on a game in order to explore LÖVE. That game is called Beathoven. It is a rhythm game based on the remix sound of the 5th symphony of Beethoven made Lionel Yu and Nicolas Chazarre. ...]]></description><link>https://sonny.alvesdi.as/beathoven-devblog-1</link><guid isPermaLink="true">https://sonny.alvesdi.as/beathoven-devblog-1</guid><category><![CDATA[#4weeks4articles]]></category><category><![CDATA[#week4]]></category><category><![CDATA[Lua]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[love]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 12 Sep 2022 03:50:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954090987/98S_aQKjk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last week at the end of that article I mentioned that I was working on a game in order to explore LÖVE. That game is called Beathoven. It is a rhythm game based on the remix sound of the 5th symphony of Beethoven made Lionel Yu and Nicolas Chazarre. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=oTjh29xo0so">https://www.youtube.com/watch?v=oTjh29xo0so</a></div>
<p>Instead of using a piano like controller, I wanted to use something a bit more like those music arcade game with button spread around the screen. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954216492/IGMWdvFpo.png" alt="MaiMai.png" class="image--center mx-auto" /></p>
<p>And I went with 4 buttons spread as a diamond. 4 buttons means 4 fingers game play, which sounds not too overwhelming, but still fun.</p>
<h2 id="heading-some-screenshots">Some screenshots</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954239734/a0HeW95rg.png" alt="image (17).png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954261024/GKIIAjKus.png" alt="title.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954278191/bz7bvwm-G.png" alt="timer.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954319640/MmrTTDmQh.png" alt="image (18).png" /></p>
<h2 id="heading-current-features">Current features</h2>
<ul>
<li>Splash screen</li>
<li>Title screen</li>
<li>Timer before actual rhythm game starts</li>
<li>Gameplay with 4 buttons (tracks) with instant pressed notes only</li>
<li>Scoring at each right note</li>
<li>HP reducing at each wrong note</li>
<li>Note streaking tracking with different messages at different levels</li>
</ul>
<h2 id="heading-planned-featureswork">Planned features/work</h2>
<ul>
<li>Game Over screen with scoring and retry button</li>
<li>Finalizing the notes balancing and rhythm</li>
<li>Adding more animation in the UI</li>
<li>Game responsive</li>
<li>Game introduction</li>
<li>Better particles effects</li>
<li>Long notes with kept-pressed buttons</li>
</ul>
<h2 id="heading-some-sharing">🤝 Some sharing</h2>
<p>It’s difficult to reduce multiple hours and several thousands lines of code in one blog article, so I’ll share a couple of things.</p>
<h3 id="heading-tracks-queue">📬 Tracks’ queue</h3>
<p>In order to save the notes currently on the track of a button, I made this Queue class (based on the classes.lua I shared in my last article.) </p>
<pre><code class="lang-lua">local classes = require "classes"

local Queue = classes.class()

function Queue:init()
    self.first = 0
    self.last = -1
    self.items = {}
end

function Queue:count()
  local count = 0
  for _ in pairs(self.items) do count = count + 1 end
  return count
end

function Queue:enqueue(value)
    self.last = self.last + 1
    self.items[self.last] = value
end

function Queue:dequeue()
  if self:count() == 0 then
    return nil
  end

  local first = self.first
  local value = self.items[first]

  self.items[first] = nil        -- to allow garbage collection
  self.first = self.first + 1

  return value
end

function Queue:deleteFirst(value)
  local i = -1
  for k = self.first,self.last,1
  do
    if self.items[k] == value then
      self.items[k] = nil
      i = k
    end
  end

  -- Value not found
  if i == -1 then
    return
  end

  for k = i,self.last,1
  do
    self.items[k] = self.items[k+1]
  end
  self.items[self.last] = nil
  self.last = self.last - 1
end

function Queue:print()
  local res = "Queue: { "
  for k,v in pairs(self.items) do
      res = res..k..": "..v..", "
  end  
  print(res.." }")
end

return Queue
</code></pre>
<p>When I press a button, a note is dequeued, and we check if the note was overlapping the button. If it was, then it’s a success and if not, then it’s an early miss. </p>
<h3 id="heading-beat-finder">🥁 Beat Finder</h3>
<p>A rhythm game means playing with the rhythm/beat of a music. </p>
<p>In order to do that, I could think of several solutions: </p>
<ul>
<li>Using Fast Fourier Transformations on the sound data to detect high frequencies peak and put a note at that moment</li>
<li>Using the 5th symphony partition</li>
<li>Using a tool like Audacity to automatically detect the beat</li>
</ul>
<p>I went with the latter, knowing that I would still have a lot of manually editing to do, to make things fun. </p>
<p>If you load a sound in audacity, you can click then on <code>Analyze</code> &gt; <code>Beat Finder</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662954498275/W1REqoILs.png" alt="audacity.png" class="image--center mx-auto" /></p>
<p>This will add a label track with a label on each beat detected. You can export it then <code>File</code> &gt; <code>Export</code> &gt; <code>Export Labels</code>. It’ll provide you a text format easily parsable. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you were looking to making a rhythm game on your own, I hope that my findings can help you to get kick-started quickly. If you are interested in Beathoven and/or would like to participate in the dev, let me know. For now, the game is not open source, but once I am happy with the state of the code and game I’ll share it.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction guide to LÖVE the 2D game engine]]></title><description><![CDATA[I will keep updating this guide from your feedback and the continuation of my exploration of LÖVE. Last update on October, 6th 2022.

Recently I decided to spend a bit of time exploring LÖVE on my spare time. It uses Lua as programming language. And ...]]></description><link>https://sonny.alvesdi.as/introduction-guide-to-love-the-2d-game-engine</link><guid isPermaLink="true">https://sonny.alvesdi.as/introduction-guide-to-love-the-2d-game-engine</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week3]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[love]]></category><category><![CDATA[Games]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 05 Sep 2022 04:19:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662351434795/UsSfDKiD2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I will keep updating this guide from your feedback and the continuation of my exploration of LÖVE. Last update on October, 6th 2022.</p>
</blockquote>
<p>Recently I decided to spend a bit of time exploring LÖVE on my spare time. It uses Lua as programming language. And is an open-source engine available for free on Windows, Mac, and Linux. You can also build your game for iOS/Android and even Web.</p>
<p>Website: <a target="_blank" href="https://love2d.org/">https://love2d.org/</a></p>
<p>I thought it would be easy coming from Unity and different others languages. But it took me a bit of time to find the information or logic behind the language and engine.</p>
<p>So I decided to write this guide to help you get kick-started and easily transitioned to LÖVE.</p>
<h1 id="heading-guide">Guide</h1>
<h2 id="heading-lua-language">Lua Language</h2>
<p>Here are some examples of different things you may want to use:</p>
<h3 id="heading-important-links">Important Links</h3>
<ul>
<li><p>Programming language reference: <strong>Programming in Lua</strong> <a target="_blank" href="https://www.lua.org/pil/contents.html">https://www.lua.org/pil/contents.html</a></p>
</li>
<li><p>Package manager for Lua: <strong>LuaRocks</strong> <a target="_blank" href="https://luarocks.org/">https://luarocks.org/</a></p>
</li>
</ul>
<h3 id="heading-variables">Variables</h3>
<pre><code class="lang-swift">local x = <span class="hljs-number">1</span> -- <span class="hljs-type">Only</span> available <span class="hljs-keyword">in</span> local scope
globalVar = <span class="hljs-number">2</span> -- <span class="hljs-type">Global</span> variable
</code></pre>
<h3 id="heading-usual-operations">Usual Operations</h3>
<pre><code class="lang-swift">-- increment variable
i = i + <span class="hljs-number">1</span>

-- decrement variable
i = i - <span class="hljs-number">1</span>

-- concatenate the variable name with two strings
message = <span class="hljs-string">"Hello, my name is "</span>..name..<span class="hljs-string">"!"</span>

-- not <span class="hljs-built_in">equal</span> <span class="hljs-keyword">operator</span> (others are the same <span class="hljs-keyword">as</span> others languages)
test = something ~= <span class="hljs-number">0</span>

-- logical operatiors: not, and, or 
test1 = not something
test2 = something and somethingelse
test3 = something or somethingelse 

-- tertiary <span class="hljs-keyword">operator</span> (a ? b : <span class="hljs-built_in">c</span>)
test = a and b or <span class="hljs-built_in">c</span>
</code></pre>
<p>Note: there is no <code>i++</code> in Lua to increment.</p>
<h3 id="heading-if-elseif-else">If, elseif, else</h3>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> playerJumped then 
  -- <span class="hljs-type">Start</span> jump animation
elseif playerCrouch then 
  -- <span class="hljs-type">Start</span> crouch animation
<span class="hljs-keyword">else</span>
  -- <span class="hljs-type">Play</span> idle animation
end
</code></pre>
<h3 id="heading-for-loops">For Loops</h3>
<pre><code class="lang-swift">-- <span class="hljs-type">Loop</span> over i from <span class="hljs-number">0</span> to <span class="hljs-number">20</span> and increment by <span class="hljs-number">1</span> at each cycle 
<span class="hljs-keyword">for</span> i = <span class="hljs-number">0</span>,<span class="hljs-number">20</span>,<span class="hljs-number">1</span>
<span class="hljs-keyword">do</span>
  -- <span class="hljs-type">Do</span> something
end
</code></pre>
<p><strong>Note</strong>: you cannot have multiple variables in the for statement. If you need multiple variables look at doing a <code>while</code> loop instead.</p>
<h3 id="heading-while-loops">While Loops</h3>
<pre><code class="lang-swift">local i = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> i &lt; <span class="hljs-number">20</span>
<span class="hljs-keyword">do</span> 
  -- <span class="hljs-type">Do</span> something 
  i = i + <span class="hljs-number">1</span>
end
</code></pre>
<h3 id="heading-functions">Functions</h3>
<pre><code class="lang-swift">function f(argument1) 
  <span class="hljs-keyword">return</span> something * argument1
end
</code></pre>
<p><strong>Note</strong>: all the primary types (numbers, boolean, nil, strings) are passed by values, everything else is passed by reference to the function.</p>
<h3 id="heading-anonymous-functions">Anonymous Functions</h3>
<h4 id="heading-inline-argument">Inline argument</h4>
<pre><code class="lang-swift"><span class="hljs-keyword">do</span>(function()
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello!"</span>)
end)
</code></pre>
<h4 id="heading-variable">Variable</h4>
<pre><code class="lang-swift">myfunc = function(n)
    <span class="hljs-keyword">return</span> n*n
end

-- example of call
myfunc(<span class="hljs-number">5</span>)

-- example of use <span class="hljs-keyword">as</span> argument
<span class="hljs-keyword">do</span>(myfunc)
</code></pre>
<h3 id="heading-classes-and-oop">Classes and OOP</h3>
<p>There is a native way of doing it, using the official language reference: <a target="_blank" href="https://www.lua.org/pil/16.1.html">https://www.lua.org/pil/16.1.html</a></p>
<p>But I found a bit inelegantly and the function <code>setmetadatatable</code> is confusing.</p>
<p>So I found another solution that simplifies the code you need to write to create classes and child classes: <a target="_blank" href="https://gist.github.com/paulmoore/1429475">https://gist.github.com/paulmoore/1429475</a></p>
<p>You only need to import the file <code>classes.lua</code> in your project, but definitely look the examples.</p>
<p>But here is a quick example.</p>
<pre><code class="lang-swift">-- <span class="hljs-type">Load</span> the classes helper file
local classes = require <span class="hljs-string">"classes"</span>

local <span class="hljs-type">Enemy</span> = classes.<span class="hljs-keyword">class</span>() -- <span class="hljs-type">Create</span> a <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">without</span> <span class="hljs-title">any</span> <span class="hljs-title">parent</span>

<span class="hljs-title">Enemy</span>.<span class="hljs-title">count</span> = 0

<span class="hljs-title">function</span> <span class="hljs-title">Enemy</span>:<span class="hljs-title">init</span>(<span class="hljs-title">name</span>)
    <span class="hljs-title">self</span>.<span class="hljs-title">hp</span> = 100
    <span class="hljs-title">self</span>.<span class="hljs-title">name</span> = <span class="hljs-title">name</span>
  <span class="hljs-title">Enemy</span>.<span class="hljs-title">count</span> = <span class="hljs-title">Enemy</span>.<span class="hljs-title">count</span> + 1
<span class="hljs-title">end</span>

-- <span class="hljs-title">static</span> <span class="hljs-title">function</span>
<span class="hljs-title">function</span> <span class="hljs-title">Enemy</span>.<span class="hljs-title">count</span>()
  <span class="hljs-title">return</span> <span class="hljs-title">Enemy</span>.<span class="hljs-title">count</span>
<span class="hljs-title">end</span>

<span class="hljs-title">local</span> <span class="hljs-title">Orc</span> = <span class="hljs-title">classes</span>.<span class="hljs-title">class</span>(<span class="hljs-title">Enemy</span>) -- <span class="hljs-title">Create</span> <span class="hljs-title">an</span> <span class="hljs-title">Orc</span> <span class="hljs-title">who</span> <span class="hljs-title">is</span> <span class="hljs-title">an</span> <span class="hljs-title">enemy</span>

<span class="hljs-title">function</span> <span class="hljs-title">Orc</span>:<span class="hljs-title">init</span>(<span class="hljs-title">name</span>, <span class="hljs-title">weapon</span>)
  <span class="hljs-title">self</span>.<span class="hljs-title">super</span>:<span class="hljs-title">init</span>(<span class="hljs-title">name</span>) -- <span class="hljs-title">call</span> <span class="hljs-title">to</span> <span class="hljs-title">parent</span> <span class="hljs-title">constructor</span>
    <span class="hljs-title">self</span>.<span class="hljs-title">weapon</span> = <span class="hljs-title">weapon</span>
<span class="hljs-title">end</span>

-- <span class="hljs-title">Instantiate</span> <span class="hljs-title">some</span> <span class="hljs-title">orcs</span> 
<span class="hljs-title">local</span> <span class="hljs-title">orcWithAxe</span> = <span class="hljs-title">Orc</span>.<span class="hljs-title">new</span>("<span class="hljs-title">Zotor</span>", "<span class="hljs-title">Axe</span>")
<span class="hljs-title">local</span> <span class="hljs-title">orcWithBow</span> = <span class="hljs-title">Orc</span>.<span class="hljs-title">new</span>("<span class="hljs-title">Plead</span>", "<span class="hljs-title">Bow</span>")</span>
</code></pre>
<p>Notes:</p>
<ul>
<li><p>We use <code>new</code> to instantiate and define <code>init</code> in the class, which is called implicitly during the <code>new</code> operation.</p>
</li>
<li><p>For static methods and variables, use the class name followed by a <code>.</code> then the name of the element you want to access.</p>
</li>
<li><p>For object methods and attributes, use the variable name followed by a <code>:</code> then the name of the element you want to access.</p>
</li>
<li><p>For private methods, don’t prefix the name of the function with the name of the class.</p>
</li>
</ul>
<h3 id="heading-queues-and-stacks">Queues and Stacks</h3>
<p>For that I made a module based on the example provided by the official language reference. <a target="_blank" href="https://www.lua.org/pil/11.4.html">https://www.lua.org/pil/11.4.html</a></p>
<pre><code class="lang-swift"><span class="hljs-type">List</span> = {}
function <span class="hljs-type">List</span>.new ()
  <span class="hljs-keyword">return</span> {first = <span class="hljs-number">0</span>, last = -<span class="hljs-number">1</span>}
end

function <span class="hljs-type">List</span>.<span class="hljs-built_in">count</span>(l)
  <span class="hljs-keyword">return</span> #table
end

function <span class="hljs-type">List</span>.pushleft (list, value)
    local first = list.first - <span class="hljs-number">1</span>
    list.first = first
    list[first] = value
  end

  function <span class="hljs-type">List</span>.pushright (list, value)
    local last = list.last + <span class="hljs-number">1</span>
    list.last = last
    list[last] = value
  end

  function <span class="hljs-type">List</span>.popleft (list)
    local first = list.first
    <span class="hljs-keyword">if</span> first &gt; list.last then error(<span class="hljs-string">"list is empty"</span>) end
    local value = list[first]
    list[first] = <span class="hljs-literal">nil</span>        -- to allow garbage collection
    list.first = first + <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> value
  end

  function <span class="hljs-type">List</span>.popright (list)
    local last = list.last
    <span class="hljs-keyword">if</span> list.first &gt; last then error(<span class="hljs-string">"list is empty"</span>) end
    local value = list[last]
    list[last] = <span class="hljs-literal">nil</span>         -- to allow garbage collection
    list.last = last - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> value
  end

<span class="hljs-keyword">return</span> <span class="hljs-type">List</span>
</code></pre>
<p>Copy that in a file <code>list.lua</code> in your project. Then you can use that way:</p>
<pre><code class="lang-swift">queue = <span class="hljs-type">List</span>.new()
stack = <span class="hljs-type">List</span>.new()

-- <span class="hljs-type">Enqueue</span> values
<span class="hljs-type">List</span>.pushright(queue, someValue)
<span class="hljs-type">List</span>.pushright(queue, someValue)
<span class="hljs-type">List</span>.pushright(queue, someValue)

-- <span class="hljs-type">Stack</span> values
<span class="hljs-type">List</span>.pushleft(stack, someValue)
<span class="hljs-type">List</span>.pushleft(stack, someValue)
<span class="hljs-type">List</span>.pushleft(stack, someValue)

-- <span class="hljs-type">Consume</span> queue (<span class="hljs-type">FIFO</span>)
local value1 = <span class="hljs-type">List</span>.popleft(queue)
local value2 = <span class="hljs-type">List</span>.popleft(queue)

-- <span class="hljs-type">Consume</span> stack (<span class="hljs-type">LIFO</span>)
local value3 = <span class="hljs-type">List</span>.popleft(stack)
local value4 = <span class="hljs-type">List</span>.popleft(stack)
</code></pre>
<h3 id="heading-arrays-and-tables-structured-data">Arrays and Tables (structured data)</h3>
<p>Table is specific type in Lua, it’s a bit like arrays in PHP which can be associative or indexed.</p>
<pre><code class="lang-swift">-- same initialization
local array = {}
local table = {}

-- initializing array values
<span class="hljs-keyword">for</span> i = <span class="hljs-number">0</span>,<span class="hljs-number">20</span>,<span class="hljs-number">1</span>
<span class="hljs-keyword">do</span> 
    array[i] = i
end

-- initialization table values
table[<span class="hljs-string">"x"</span>] = <span class="hljs-number">0</span>
table[<span class="hljs-string">"y"</span>] = <span class="hljs-number">0</span>

-- or could be done at the declaration
local coords = {x=<span class="hljs-number">0</span>, y=<span class="hljs-number">0</span>}
</code></pre>
<h3 id="heading-cron">Cron</h3>
<p>If you want to schedule a specific action at a certain time, you want to use cron/timer. The easiest solution I found is to use the tool made by kikito: <a target="_blank" href="https://github.com/kikito/cron.lua">https://github.com/kikito/cron.lua</a></p>
<pre><code class="lang-swift">local cron = require 'cron'

local function printMessage()
  <span class="hljs-built_in">print</span>('<span class="hljs-type">Hello'</span>)
end

-- the following calls are equivalent:
local c1 = cron.after(<span class="hljs-number">5</span>, printMessage)
local c2 = cron.after(<span class="hljs-number">5</span>, <span class="hljs-built_in">print</span>, '<span class="hljs-type">Hello'</span>)

c1:update(<span class="hljs-number">2</span>) -- will <span class="hljs-built_in">print</span> nothing, the action <span class="hljs-keyword">is</span> not done yet
c1:update(<span class="hljs-number">5</span>) -- will <span class="hljs-built_in">print</span> '<span class="hljs-type">Hello'</span> once

c1:reset() -- reset the counter to <span class="hljs-number">0</span>

-- prints 'hey' <span class="hljs-number">5</span> times and then prints 'hello'
<span class="hljs-keyword">while</span> not c1:update(<span class="hljs-number">1</span>) <span class="hljs-keyword">do</span>
  <span class="hljs-built_in">print</span>('hey')
end

-- <span class="hljs-type">Create</span> a periodical clock:
local c3 = cron.every(<span class="hljs-number">10</span>, printMessage)

c3:update(<span class="hljs-number">5</span>) -- nothing (total time: <span class="hljs-number">5</span>)
c3:update(<span class="hljs-number">4</span>) -- nothing (total time: <span class="hljs-number">9</span>)
c3:update(<span class="hljs-number">12</span>) -- prints '<span class="hljs-type">Hello'</span> twice (total time <span class="hljs-keyword">is</span> now <span class="hljs-number">21</span>)
</code></pre>
<h2 id="heading-love-engine-specifics">LÖVE Engine Specifics</h2>
<p>OK, Lua itself requires some learning as you’ve seen. But LÖVE too!</p>
<h3 id="heading-important-links-1">Important Links</h3>
<ul>
<li>Official documentation: LÖVE Wiki <a target="_blank" href="https://love2d.org/wiki/Main_Page">https://love2d.org/wiki/Main_Page</a></li>
</ul>
<h3 id="heading-structure">Structure</h3>
<p>To run a game you need a folder with a <code>main.lua</code> at least.</p>
<p>Example of minimal structure:</p>
<pre><code class="lang-swift">function love.load()
    -- <span class="hljs-type">Run</span> once at game initialization
end

function love.keypressed(key, scancode, isrepeat)
    -- <span class="hljs-type">Run</span> each time a key on the keyboard <span class="hljs-keyword">is</span> pressed
end

function love.mousepressed(x, y, button, istouch, presses)
    -- <span class="hljs-type">Run</span> each time a mouse button <span class="hljs-keyword">is</span> pressed, supports multi-touch too
end

function love.update(dt)
    -- <span class="hljs-type">Run</span> at each frame before drawing it
    -- <span class="hljs-type">This</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">where</span> you handle most of your game logic
end

function love.draw()
  -- <span class="hljs-type">Called</span> at every frame to draw the game
end
</code></pre>
<p><strong>Note</strong>: There are others functions you may need you can find the details here: <a target="_blank" href="https://love2d.org/wiki/love">https://love2d.org/wiki/love</a></p>
<h3 id="heading-ide">IDE</h3>
<p>I advice you to use Visual Code with the extension <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=SK83RJOSH.love-launcher">https://marketplace.visualstudio.com/items?itemName=SK83RJOSH.love-launcher</a></p>
<p>Also add a file <code>conf.lua</code> at the root of your folder, with that contents:</p>
<pre><code class="lang-swift">function love.conf(t)
    t.console = <span class="hljs-literal">true</span>
end
</code></pre>
<p>Now each time you press <code>Alt+L</code>, your game will pop plus the console window which can help to debug.</p>
<h3 id="heading-manipulate-the-game-window">Manipulate the Game Window</h3>
<p>You can change the default window display attribute during load of your game. Example:</p>
<pre><code class="lang-swift">function love.load()
    love.window.setMode(<span class="hljs-number">800</span>, <span class="hljs-number">600</span>, {resizable=<span class="hljs-literal">true</span>, minwidth=<span class="hljs-number">400</span>, minheight=<span class="hljs-number">300</span>})
end
</code></pre>
<p><strong>Details</strong>: <a target="_blank" href="https://love2d.org/wiki/love.window.setMode">https://love2d.org/wiki/love.window.setMode</a></p>
<h3 id="heading-svg-files">SVG Files</h3>
<p>I found a nice package that add supports of SVG files to LÖVE. It is called TÖVE.</p>
<p><strong>Details</strong>: <a target="_blank" href="https://github.com/poke1024/tove2d">https://github.com/poke1024/tove2d</a></p>
<p>No active development since a couple of years ago, so be aware of that. But for me it worked fine.</p>
<h3 id="heading-fixed-update">Fixed Update</h3>
<p>If you want to make your game at a constant framerate, it’s not possible natively.</p>
<p>But I found that gist from Leandros: <a target="_blank" href="https://gist.github.com/Leandros/98624b9b9d9d26df18c4">https://gist.github.com/Leandros/98624b9b9d9d26df18c4</a> that just does the job perfectly.</p>
<p>You need to copy/paste the code at the end of your <a target="_blank" href="http://main.ly">main.l</a>ua and that’s it. Constant 60FPS.</p>
<p>You can tweak the FPS if you need.</p>
<h3 id="heading-ecs-entity-component-system">ECS (Entity Component System)</h3>
<p>LÖVE is not natively using the paradigm <a target="_blank" href="%5Bhttps://en.wikipedia.org/wiki/Entity_component_system%5D(https://en.wikipedia.org/wiki/Entity_component_system)">ECS</a>. But if you like ECS like I do, I found a tiny ECS framework for it. It was written in 2016, pretty old already, but it’s that tiny that it did age well.</p>
<p>Here is the link about: <a target="_blank" href="https://github.com/bakpakin/tiny-ecs">https://github.com/bakpakin/tiny-ecs</a></p>
<p>If you want to use it there’s only one file <code>tiny.lua</code> to copy to your project.</p>
<p>You can find a project using it here as example: <a target="_blank" href="https://github.com/bakpakin/CommandoKibbles">https://github.com/bakpakin/CommandoKibbles</a></p>
<h3 id="heading-post-processing-screen-vfx">Post Processing Screen VFX</h3>
<p>If you want to have some post processing screen virtual effects, the easiest I found is to use moonshine: <a target="_blank" href="https://github.com/vrld/moonshine">https://github.com/vrld/moonshine</a></p>
<p>It contains 16 effects like glow, vignette, crt, .. that you can chain as you want and change parameters on the fly.</p>
<p>If you want to create your own effect you will have to start write shaders and extend moonshine effects.</p>
<p>Check the github README to understand how to use it.</p>
<h3 id="heading-screen-shake-effect">Screen Shake Effect</h3>
<p>I found on the forum of LÖVE a reply from vrld that does the job: <a target="_blank" href="https://love2d.org/forums/viewtopic.php?p=193765#p193765">https://love2d.org/forums/viewtopic.php?p=193765#p193765</a></p>
<pre><code class="lang-swift">local t, shakeDuration, shakeMagnitude = <span class="hljs-number">0</span>, -<span class="hljs-number">1</span>, <span class="hljs-number">0</span>
function startShake(duration, magnitude)
    t, shakeDuration, shakeMagnitude = <span class="hljs-number">0</span>, duration or <span class="hljs-number">1</span>, magnitude or <span class="hljs-number">5</span>
end

function love.update(dt)
    <span class="hljs-keyword">if</span> t &lt; shakeDuration then
        t = t + dt
    end
end

function love.draw()
    <span class="hljs-keyword">if</span> t &lt; shakeDuration then
        local dx = love.math.random(-shakeMagnitude, shakeMagnitude)
        local dy = love.math.random(-shakeMagnitude, shakeMagnitude)
        love.graphics.translate(dx, dy)
    end
end
</code></pre>
<h2 id="heading-game-distribution">Game distribution</h2>
<p>If you want to distribute your game, your starting point is the wiki at that address: https://love2d.org/wiki/Game_Distribution</p>
<h3 id="heading-more-details-on-weggl">More details on WegGL</h3>
<p>First, you need to install the tool from Davidobot: <a target="_blank" href="https://github.com/Davidobot/love.js">https://github.com/Davidobot/love.js</a></p>
<pre><code class="lang-bash">npm install -g love.js
</code></pre>
<p><strong>Web server with proper headers</strong></p>
<p>Then you will need a server and a web server running on it. On my end, I use Nginx, and this is how I configured my <code>location</code>:</p>
<pre><code class="lang-swift">location /beathoven/ {
        add_header <span class="hljs-type">Cross</span>-<span class="hljs-type">Origin</span>-<span class="hljs-type">Opener</span>-<span class="hljs-type">Policy</span> same-origin;
        add_header <span class="hljs-type">Cross</span>-<span class="hljs-type">Origin</span>-<span class="hljs-type">Embedder</span>-<span class="hljs-type">Policy</span> require-corp;
        alias /usr/share/nginx/html/beathoven/;
}
</code></pre>
<p><strong>Add missing mime type</strong></p>
<p>After several tries looking at errors in browser, I realize also I needed to edit the file <code>/etc/nginx/mime.types</code> to add the definition for wasm file:</p>
<pre><code class="lang-swift">    application/vnd.google-earth.kmz      kmz;
    application/wasm                      wasm;
    application/x-7z-compressed           7z;
</code></pre>
<p><strong>Use 7zip not tar on Windows</strong></p>
<p>To package your game into a love file, you need to simply zip the files.</p>
<p>And since Windows 10, it includes a <code>tar</code> command line utility that you can use to make zip in scripts. But it looks like it’s not supported by the WebGL build. So I switched to 7Zip using the following parameters:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665027812714/ekWI08TXe.png" alt="Untitled.png" /></p>
<p>You can also use 7zip in command line.</p>
<p><strong>Example of build &amp; deploy script</strong></p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

tools/7za a -tzip Beathoven.zip assets/ gameobjects/ pages/ responsive/ utils/ fonts.lua main.lua -mx0
mv Beathoven.zip Beathoven.love

love.js -t Beathoven -c Beathoven.love game 

ssh server rm -rf /usr/share/nginx/html/beathoven/*

scp -r game/* server:/usr/share/nginx/html/beathoven/
</code></pre>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Obviously I haven’t covered everything here, but I hope that it can give a nice introduction to help you getting quickly productive with LÖVE and create some cool games!</p>
<p>Next week I’ll share about a Rhythm game called Beathoven I decided to make while exploring about the possibilities of LÖVE.</p>
]]></content:encoded></item><item><title><![CDATA[I may be a Nintendo fanboy, but...]]></title><description><![CDATA[From the POV of a game developer
I admire the quality of their work. 

They polish their games very well!
Their games have very few bugs.
They perfect the gameplay of their games through generations, like Mario.
But they take risks and try new things...]]></description><link>https://sonny.alvesdi.as/i-may-be-a-nintendo-fanboy-but</link><guid isPermaLink="true">https://sonny.alvesdi.as/i-may-be-a-nintendo-fanboy-but</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week2]]></category><category><![CDATA[Video games]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 29 Aug 2022 04:38:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/PJEyTCV1aFs/upload/v1661743434914/AXpfjmKNF.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-from-the-pov-of-a-game-developer">From the POV of a game developer</h2>
<p>I admire the quality of their work. </p>
<ul>
<li>They polish their games very well!</li>
<li>Their games have very few bugs.</li>
<li>They perfect the gameplay of their games through generations, like Mario.</li>
<li>But they take risks and try new things, like making an open world with Zelda Breath of the Wild.</li>
<li>They focus on the game experience, offering their best in gaming every time. </li>
</ul>
<p>To me, Nintendo has truly been the most significant actor in video games. They helped to democratize video games with their Famicom. And nailed the mass adoption with the Wii and more recently the Switch. </p>
<p>It's very exceptional that a company is by itself defining and representing a whole industry. </p>
<h2 id="heading-from-the-pov-of-a-company-executive">From the POV of a company executive</h2>
<p>On top of their longevity, I am impressed by their courage and vision. </p>
<ul>
<li>They launched the Game Boy while its hardware was already obsolete, somehow. But making a huge success with it because of its cheap price, autonomy, and good catalog of games.</li>
<li>After the Nintendo 64, their competitors entered a race for the most powerful consoles. While they stuck to their vision and principles, which lead to their success with the Wii. </li>
<li>Since ever, they always had two major hardware products at any time: a home console and a portable console. They made the bet of creating a hybrid product: the Switch, both a home and portable console, and met success with it!</li>
</ul>
<p>They take risks and sometimes met failures. Like with the Visual Boy, the Game Cube, or also the Wii U. But still, find the resources to rebound and change the game. </p>
<h2 id="heading-what-i-retain-from-nintendo">What I retain from Nintendo</h2>
<ul>
<li>User-centric vision</li>
<li>Taking risks to try new things</li>
<li>While reusing and perfecting the existing</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[That time I failed a university selection interview...]]></title><description><![CDATA[In June 2007, at the end of the school year, I got the opportunity to apply to the most prestigious software engineering schools in France.

A bit of context, diplomas are different in France. I was somehow in a Bachelor in Computer Science degree at...]]></description><link>https://sonny.alvesdi.as/that-time-i-failed-a-university-selection-interview</link><guid isPermaLink="true">https://sonny.alvesdi.as/that-time-i-failed-a-university-selection-interview</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[week1]]></category><category><![CDATA[Career]]></category><category><![CDATA[university]]></category><category><![CDATA[interview]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Mon, 22 Aug 2022 02:34:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/uRB7AEK8WzM/upload/v1660980772592/haX1dVPGQ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In June 2007, at the end of the school year, I got the opportunity to apply to the most prestigious software engineering schools in France.</p>
<blockquote>
<p>A bit of context, diplomas are different in France. I was somehow in a Bachelor in Computer Science degree at that time. And moving to that university would have been for a Master’s degree.</p>
</blockquote>
<h2 id="heading-what-happened">What happened</h2>
<p>All my teachers were behind me and happy to refer me to this prestigious school. Only <u>one</u> student from our school had been accepted in the past. Would I be the second?</p>
<p>I passed the initial round of selection, which was a written essay on why I wanted to go to the school. And it was enclosed with a couple of reference letters from teachers.</p>
<p>For the second round, they included different tests and would be in person. It was about two hours drive from home. And I didn't have a car.</p>
<p>My sister proposed to drive me. Problem, the interview was starting at 7.30 am (that's early...). So she proposed to host me for the night too and drive me at 5 am.</p>
<p>When it comes to sleep, whenever I don't sleep at home in my own bed, it's difficult. </p>
<p>And of course the night before, at my sister's house, I was also excited and stressed by the interview. That much that I think, I fell asleep only at 2 or even 3 am. </p>
<p>At 4.30 am, we woke up.  </p>
<p>At 5 am, we left the house and took the road.</p>
<p>At 7 am something, we arrive at the interview location. We were a bit in advance.</p>
<p>Problem, I couldn't sleep in the car either and with my sleep deprivation, I was like a drunkard.</p>
<p>I entered the room and passed these different tests. While I was completely disinhibited and over-confident from the lack of sleep.</p>
<p>There were some written tests: computer science and math, which were ok.</p>
<p>Then some group work, where I took the lead and completely silenced my group mates.</p>
<p>During the final interview, me alone facing a board of examiners, I declaimed some stupid things...</p>
<p>Going out of the room, lucidity came back, I knew I failed... </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So my advice to everyone preparing for an interview, <strong>do your best to arrive there in the best conditions</strong>. Rent a hotel if needed, not like me...</p>
<p>And in the end, if you fail, it is completely ok. There are tons of opportunities! And not going to that university definitely did not kill my career in software.</p>
]]></content:encoded></item><item><title><![CDATA[The Game Dev Parent Game Review: "My Little Pony Color By Magic"]]></title><description><![CDATA[My daughters have been playing: My Little Pony Color By Magic for a while now. The game concept is pretty simple and is relaxing, like adult coloring books. 
https://youtu.be/izJ5wy13Orw
Analysis
Pros

Pretty art and graphics.
Animation and original ...]]></description><link>https://sonny.alvesdi.as/the-game-dev-parent-game-review-my-little-pony-color-by-magic</link><guid isPermaLink="true">https://sonny.alvesdi.as/the-game-dev-parent-game-review-my-little-pony-color-by-magic</guid><category><![CDATA[Games]]></category><category><![CDATA[life]]></category><category><![CDATA[opinion pieces]]></category><category><![CDATA[review]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Fri, 06 May 2022 03:46:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/-_QpJv4J_AA/upload/v1651808761974/GiNdojasC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My daughters have been playing: <code>My Little Pony Color By Magic</code> for a while now. The game concept is pretty simple and is relaxing, like adult coloring books. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/izJ5wy13Orw">https://youtu.be/izJ5wy13Orw</a></div>
<h2 id="heading-analysis">Analysis</h2>
<h3 id="heading-pros">Pros</h3>
<ul>
<li>Pretty art and graphics.</li>
<li>Animation and original voices from the show!</li>
<li>Energy system, limiting your kid to spend hours in the game.</li>
<li>Ads system not too intrusive! And appropriate ads (This is a big plus to me).</li>
<li>Possible to play the game entirely for free.</li>
<li>Fun to play with your kids.</li>
<li>The hint system that unblocks your kids on-demand. </li>
</ul>
<h3 id="heading-cons">Cons</h3>
<ul>
<li>Very limited free colors choice on the freestyle drawings.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/RG4px8UayRHy9GR7PM/giphy.gif">https://media.giphy.com/media/RG4px8UayRHy9GR7PM/giphy.gif</a></div>
<p>Here is a game that distinguishes itself from the numerous lame and scammy games you can find on the mobile app stores! </p>
<p>The game looks good. The concept is simple and relaxing. It uses well the touch screen. The game has good limitations so that your kid doesn't spend hours on it. While not forcing your hand to pay for it and having ads that are not that much intrusive.</p>
<p>A game I recommend to other parents! Congrats to Budge Studios for this one. </p>
<h3 id="heading-links">Links</h3>
<ul>
<li><a target="_blank" href="https://play.google.com/store/apps/details?id=com.budgestudios.googleplay.MyLittlePonyColoring&amp;hl=en_US&amp;gl=US">Google Play</a> </li>
<li><a target="_blank" href="https://apps.apple.com/us/app/my-little-pony-color-by-magic/id1495392781">Apple Store</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[My Shell Config On Windows For 2022]]></title><description><![CDATA[Last year I wrote an article about my shell config for 2021. 
https://sonny.alvesdi.as/my-shell-config-on-windows-for-2021
I am renewing the operation this year, and to be straightforward with you 
I gave up on Alacritty
Alacritty is nice, but in dai...]]></description><link>https://sonny.alvesdi.as/my-shell-config-on-windows-for-2022</link><guid isPermaLink="true">https://sonny.alvesdi.as/my-shell-config-on-windows-for-2022</guid><category><![CDATA[shell]]></category><category><![CDATA[Bash]]></category><category><![CDATA[terminal]]></category><category><![CDATA[console]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Wed, 27 Apr 2022 04:02:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/vk0zqWdpGLk/upload/v1651031840354/63XzLJz8C.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last year I wrote an article about my shell config for 2021. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://sonny.alvesdi.as/my-shell-config-on-windows-for-2021">https://sonny.alvesdi.as/my-shell-config-on-windows-for-2021</a></div>
<p>I am renewing the operation this year, and to be straightforward with you </p>
<h2 id="heading-i-gave-up-on-alacritty">I gave up on Alacritty</h2>
<p>Alacritty is nice, but in daily life there were a lot of frictions (that are maybe fixed by now TBH) especially for copy/pasting string into the shell. Also, IIRC no tabs or such. </p>
<h2 id="heading-so-what-am-i-using-now">So what am I using now?</h2>
<p>I switched to <strong>Hyper</strong>! It's an electron-based terminal made by Vercel, the company that offers this platform to greatly ease the deployment of an app. I recommend Vercel and glitch.com also if you want to deploy a small or website easily. </p>
<blockquote>
<p>Download link: https://hyper.is/ </p>
</blockquote>
<p>To make Hyper work with the usual Git Bash, I changed that line in the configuration: </p>
<pre><code class="lang-json">        shell: 'C:\\Program Files\\Git\\bin\\bash.exe',
</code></pre>
<p>And to directly copy selected text to clipboard, I changed that line to <code>true</code>:</p>
<pre><code class="lang-json">        copyOnSelect: <span class="hljs-literal">true</span>,
</code></pre>
<p>I didn't change much more aside the font. </p>
<h2 id="heading-new-year-new-font">New year, new font</h2>
<p>Last year I recommended Fira Code. This year I would recommend you <strong>Monoid </strong>an open source coding font, more details there: https://larsenwork.com/monoid/</p>
<h2 id="heading-other-suggestions">Other suggestions</h2>
<ul>
<li>If you want an easy way to install and uninstall software from the command line on Windows, check out chocolatey.org</li>
<li>If you use Git Bash and Docker like me, you probably want to add that line to your <code>~/.bashrc</code>: <pre><code class="lang-bash"><span class="hljs-built_in">alias</span> docker=<span class="hljs-string">'MSYS_NO_PATHCONV=1 docker'</span>
</code></pre>
That will allow you to do things like: <code>docker exec -ti ${CONTAINER} /bin/bash</code> directly from Git Bash. </li>
<li>Also, if you use one of the latest Git Bash, there's a bug that creates troubles when you ssh into a server. Symptoms are like you can't use <code>vi</code> or <code>CTRC+C</code> will quit the entire ssh session. Add the following line in your <code>~/.bashrc</code> as well, and it will fix it.<pre><code class="lang-bash"><span class="hljs-built_in">export</span> MSYS=enable_pcon
</code></pre>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Introduction to Liquid for developers]]></title><description><![CDATA[If you are going to work on software using Liquid, the sidechain of Bitcoin, there are several concepts you need to be familiar with. This article aims at developers and is based on a presentation I held for the Pixelmatic team.

Disclaimer: this is ...]]></description><link>https://sonny.alvesdi.as/introduction-to-liquid-for-developers</link><guid isPermaLink="true">https://sonny.alvesdi.as/introduction-to-liquid-for-developers</guid><category><![CDATA[Bitcoin]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[NFT]]></category><category><![CDATA[crypto]]></category><category><![CDATA[THW Web3]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Tue, 19 Apr 2022 04:54:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/UeBFFAPwuj8/upload/v1644131978625/UHPahCUJ6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are going to work on software using Liquid, the sidechain of Bitcoin, there are several concepts you need to be familiar with. This article aims at developers and is based on a presentation I held for the Pixelmatic team.</p>
<blockquote>
<p>Disclaimer: this is an introduction and it does not cover everything obviously. And I simplified some explanations on purpose.</p>
</blockquote>
<p>As a prerequisite, if you are not familiar with Bitcoin, you should read my introduction to Bitcoin here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://sonny.alvesdi.as/introduction-to-bitcoin-for-developers">https://sonny.alvesdi.as/introduction-to-bitcoin-for-developers</a></div>
<p> </p>
<p>*Special thanks to <a target="_blank" href="https://twitter.com/Sosthene___">Sosthene</a> for proofreading my article and his feedback! Follow him on Twitter. *</p>
<p>Let's start now! And to discuss Liquid, we need to discuss first: <strong>Elements</strong>.</p>
<h2 id="heading-what-is-elements">What is Elements?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647159365664/CpMJT2EpS.png" alt="image.png" /></p>
<p>It is a fork of Bitcoin extended to be a sidechain platform with these features:</p>
<ul>
<li><p>Confidential Transactions</p>
</li>
<li><p>Issued Assets</p>
</li>
<li><p>Federated 2-Way Pegs</p>
</li>
<li><p>Signed Blocks</p>
</li>
<li><p>Additional opcodes</p>
</li>
</ul>
<p>Source: <a target="_blank" href="https://elementsproject.org/">https://elementsproject.org/</a></p>
<hr />
<h1 id="heading-ok-whatever-but-whats-liquid">OK, whatever, but what’s Liquid?</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647159427662/_NgaMZfIn.png" alt="image.png" /></p>
<ul>
<li><p>Well Liquid is <strong>an instance of Elements</strong>. Set as <strong>a sidechain of Bitcoin</strong> and maintained by Blockstream.</p>
</li>
<li><p>It is managed by a static federation of 15 members, but soon dynamic.</p>
</li>
<li><p>It is configured to have a block time of 1 minute.</p>
</li>
<li><p>And its main currency is L-BTC (Liquid Bitcoin), the result of the pegging of Bitcoin.</p>
</li>
</ul>
<p>More details: <a target="_blank" href="https://liquid.net">liquid.net</a></p>
<hr />
<h1 id="heading-what-are-the-features-of-liquid">What are the features of Liquid?</h1>
<p>Let’s see a bit more details on the different features of Liquid/Elements.</p>
<h2 id="heading-2-way-pegging-of-bitcoin">2-way pegging of Bitcoin</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644771342161/OF7V8mNmd.gif" alt="DpeluCGXcAA3bbP.gif" /></p>
<h3 id="heading-peg-in">Peg-in</h3>
<p>Pegging in BTC from the Bitcoin mainnet into the Liquid sidechain consists of depositing BTC into the Liquid Bitcoin wallet that is managed by the Federation. 102 confirmations on the Bitcoin mainnet are then required for you to claim your amount of L-BTC due, and the functionaries then grant you the corresponding amount on the Liquid sidechain.</p>
<h3 id="heading-peg-out">Peg-out</h3>
<p>Pegging out BTC from the Liquid sidechain back into the Bitcoin mainnet consists of receiving the BTC from an anonymous functionary from his wallet after being granted the amount by the federation.<br />2 confirmations on Liquid are required for the operation to be allowed. Then the Federation will co-sign a transaction out of their 11 of 15 multisig wallet that is sending out the amount requested to one of the functionaries described anonymously. Finally, the functionary processes the transaction that will grant the BTC to the requester of the peg-out.</p>
<h2 id="heading-confidential-transactions">🙈 Confidential Transactions</h2>
<ul>
<li><p>Amounts and assets are blinded using a blinding key, but UTXOs are visible</p>
</li>
<li><p>There is a master blinding key that is generated from the wallet seed and derived as needed for each address:</p>
</li>
</ul>
<pre><code class="lang-bash">blinding_private_key := HMAC_SHA256(key=master_blinding_key, msg=script_pubkey)
</code></pre>
<p>where <code>script_pubkey</code> corresponds to a specific non-confidential public address you want to make confidential</p>
<ul>
<li><p>That means that a Liquid wallet consists of two things: an extended private key and a master blinding key.</p>
</li>
<li><p>Also, every confidential address is a non-confidential address blinded using the master blinding key. So the confidentiality is essentially a layer built on the top of classical HD wallets.</p>
</li>
<li><p>Note that you can dump a specific blinding key to allow a tier to unblind it using the RPC <code>unblindrawtransaction</code>. And once in possession of the blinding key, any transaction happening with that specific address will be visible to the tier.</p>
<blockquote>
<p>FYI Blockstream Green has a feature to open esplora with the blinding keys to allow a tier to see a confidential transaction unblinded on the web.</p>
</blockquote>
</li>
</ul>
<p><img src="https://help.blockstream.com/hc/article_attachments/900001956726/20200615_confidential_transaction_diagram1200px800px.png" alt="CT" /></p>
<p>White Paper: <a target="_blank" href="https://blockstream.com/bitcoin17-final41.pdf">Blockstream</a></p>
<p>Specifications: <a target="_blank" href="https://github.com/satoshilabs/slips/blob/master/slip-0077.md">Satoshi Labs</a></p>
<hr />
<h2 id="heading-issued-assets">💰 Issued Assets</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647160651648/JM58glYNG.png" alt="image.png" /></p>
<ul>
<li><p>One asset on Liquid/Elements has these attributes (all saved in the blockchain):</p>
<ul>
<li><p>An asset ID (generated by Liquid)</p>
</li>
<li><p>A total supply</p>
</li>
<li><p>An optional reissuance key</p>
</li>
<li><p>An optional contract hash</p>
</li>
</ul>
</li>
<li><p>Reissuance keys are also an asset that comes with at least a total supply of 1 sat</p>
</li>
<li><p>L-BTC is also an asset, a special one that can be pegged in and out: <a target="_blank" href="https://blockstream.info/liquid/asset/6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d">Details</a></p>
</li>
<li><p>The bare minimum to issue an asset:</p>
</li>
</ul>
<pre><code class="lang-bash">elements-cli issueasset 0.00000100 0
</code></pre>
<p>-&gt; It issues a confidential asset with a total supply of 100 satoshis and no reissuance key.</p>
<ul>
<li>The contract defines metadata about the asset like its name, ticker, domain owner, precision, etc. <a target="_blank" href="https://blockstream.info/liquid/asset/52d77159096eed69c73862a30b0d4012b88cedf92d518f98bc5fc8d34b6c27c9">Example the EXOeu token</a>:</li>
</ul>
<pre><code class="lang-json">{
 <span class="hljs-attr">"entity"</span>: {
  <span class="hljs-attr">"domain"</span>: <span class="hljs-string">"exordium.co"</span>
 },
 <span class="hljs-attr">"issuer_pubkey"</span>: <span class="hljs-string">"030cff26f9c0d365f090e24917277e23269d7ef5d7f06dec9f09de9255b8950208"</span>,
 <span class="hljs-attr">"name"</span>: <span class="hljs-string">"EXO Token Europe"</span>,
 <span class="hljs-attr">"precision"</span>: <span class="hljs-number">0</span>,
 <span class="hljs-attr">"ticker"</span>: <span class="hljs-string">"EXOeu"</span>,
 <span class="hljs-attr">"version"</span>: <span class="hljs-number">0</span>
}
</code></pre>
<h3 id="heading-reissuance">Reissuance</h3>
<ul>
<li><p>To be able to reissue, you need only one token (satoshi) of the reissuance asset.</p>
</li>
<li><p>If you have issued more than one reissuance asset, it means you can share that asset to others person. Then everybody who has one can reissue the asset. Though be cautious with that use-case because reissuance can be confidential, then it's nearly impossible to verify how much of the asset is in circulation.</p>
</li>
</ul>
<h3 id="heading-registration">Registration</h3>
<ul>
<li><p>By default, assets are not registered on the Liquid Asset Registry.</p>
</li>
<li><p>That gives you a chance to reissue another asset if you made a mistake before registering it.</p>
</li>
<li><p>But once registered, it is irreversible and the tuple domain + ticker will be occupied forever.</p>
</li>
<li><p>Details of the asset registration: https://docs.blockstream.com/liquid/developer-guide/proof-of-issuance.html</p>
</li>
</ul>
<hr />
<h2 id="heading-federation">🪢 Federation</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647160752665/J2-eOSOy6.png" alt="image.png" /></p>
<ul>
<li><p>The federation is composed of 15 functionaries</p>
</li>
<li><p>They can propose blocks to be added to the blockchain in a round-robin fashion</p>
</li>
<li><p>They co-sign blocks, a block needs 11 of 15 signatures to be valid</p>
</li>
<li><p>They process peg-outs.</p>
</li>
<li><p>When the federation will become dynamic, the total number of functionaries may vary dynamically</p>
</li>
</ul>
<hr />
<h2 id="heading-liquid-rpc-interface">📃 Liquid RPC interface</h2>
<p>Being a fork of Bitcoin, we find the same RPCs as its parent, plus some new ones like <code>issueasset</code>, <code>blindrawtransaction</code>, and more:</p>
<p>Source: <a target="_blank" href="https://elementsproject.org/en/doc/0.21.0.0/rpc/">elementsproject.org</a></p>
<hr />
<h2 id="heading-the-liquid-ecosystem">🧰 The Liquid Ecosystem</h2>
<h3 id="heading-for-users">For Users</h3>
<h4 id="heading-white-paper">White paper</h4>
<ul>
<li>Liquid: https://blockstream.com/assets/downloads/pdf/liquid-whitepaper.pdf</li>
</ul>
<h4 id="heading-compatible-wallets">Compatible Wallets</h4>
<ul>
<li><p>Green: https://blockstream.com/green/</p>
</li>
<li><p>Aqua: https://blockstream.com/aqua/</p>
</li>
<li><p>SideSwap: https://sideswap.io/</p>
</li>
<li><p>Coinos: https://coinos.io/</p>
</li>
<li><p>Specter: https://specter.solutions/</p>
</li>
<li><p>Marina: https://vulpem.com/marina.html</p>
</li>
</ul>
<h4 id="heading-centralized-exchanges">Centralized Exchanges</h4>
<ul>
<li><p>Bitfinex: https://www.bitfinex.com/</p>
</li>
<li><p>BTSE: https://www.btse.com/</p>
</li>
<li><p>The Rock Trading: https://www.therocktrading.com/en/</p>
</li>
<li><p>...</p>
</li>
</ul>
<h4 id="heading-dexswap">DEX/Swap</h4>
<ul>
<li><p>Sideshift.ai: https://sideshift.ai/</p>
</li>
<li><p>SideSwap: https://sideswap.io/</p>
</li>
<li><p>Bisq: https://bisq.network/</p>
</li>
<li><p>coinos: https://coinos.io/</p>
</li>
<li><p>TDEX: https://dev.tdex.network/</p>
</li>
<li><p>Bitmatrix: https://beta.bitmatrix.app/</p>
</li>
</ul>
<h4 id="heading-explorers">Explorers</h4>
<ul>
<li><p>blockstream.info: https://blockstream.info/liquid/</p>
</li>
<li><p>liquid.network: https://liquid.network/</p>
</li>
</ul>
<hr />
<h3 id="heading-for-developers">For Developers</h3>
<h4 id="heading-documentation">Documentation</h4>
<ul>
<li><p>About Elements: https://elementsproject.org/</p>
</li>
<li><p>About Liquid Testnet: https://liquidtestnet.com/</p>
</li>
<li><p>About Liquid: https://docs.blockstream.com/liquid/technical_overview.html</p>
</li>
</ul>
<h4 id="heading-node">Node</h4>
<ul>
<li>Elements: https://github.com/ElementsProject/elements</li>
</ul>
<h4 id="heading-cached-apibackend">Cached API/Backend</h4>
<ul>
<li>Blockstream ElectRS: https://github.com/Blockstream/electrs</li>
</ul>
<h4 id="heading-explorer">Explorer</h4>
<ul>
<li><p>Esplora: https://github.com/Blockstream/esplora</p>
</li>
<li><p>Blockstream Registry: https://blockstream.info/liquid/assets</p>
</li>
</ul>
<h4 id="heading-libraries">Libraries</h4>
<ul>
<li><p>Vulpem Go Elements: https://github.com/vulpemventures/go-elements</p>
</li>
<li><p>Vulpem LiquidJS: https://github.com/vulpemventures/liquidjs-lib</p>
</li>
<li><p>Vulpem LDK: https://github.com/vulpemventures/ldk</p>
</li>
<li><p>Blockstream GDK: https://github.com/Blockstream/gdk/</p>
</li>
<li><p>LibWally: https://github.com/ElementsProject/libwally-core</p>
</li>
</ul>
<h4 id="heading-wallet-tools">Wallet Tools</h4>
<ul>
<li><p>Mnemonic Code Converter: https://iancoleman.io/bip39/</p>
</li>
<li><p>BIP32 Generator: http://bip32.org/</p>
</li>
</ul>
<h4 id="heading-environment-stack">Environment stack</h4>
<ul>
<li>Nigiri: https://github.com/vulpemventures/nigiri</li>
</ul>
<hr />
<h2 id="heading-sidechain-available-environment">Sidechain available environment</h2>
<p>Alike Bitcoin, Liquid has multiple environments at your disposal.</p>
<blockquote>
<p>You can set up in your elements.conf the <code>chain</code> you want to use.</p>
</blockquote>
<h3 id="heading-liquid-regtest-chainliquidregtest"><strong>Liquid Regtest</strong> (<code>chain=liquidregtest</code>)</h3>
<ul>
<li><p>I am lying to you, actually. You can input any not known chain, and it will create an Elements environment, with the parameters of your choices. So <code>liquidregtest</code> is not a known chain, it will start a chain named with this name. But you could name it differently like andrewschain, ethereum, or whatever. Details: https://github.com/ElementsProject/elements#modes</p>
</li>
<li><p>Regtest stands for regression test mode. It's a mode you use to do local development.</p>
</li>
<li><p>When initializing your node, you can specify the number of free coins you will create and that will serve as your main currency (your own test Bitcoins).</p>
</li>
<li><p>There are no pegging, mining, or federations in place. But you can generate blocks on demand.</p>
</li>
<li><p>To simulate a production environment, you can set up a cron task to generate a block every minute.</p>
</li>
<li><p>Everything you do stays local in your node.</p>
</li>
</ul>
<h3 id="heading-liquid-testnet-chainliquidtestnet"><strong>Liquid Testnet</strong> (<code>chain=liquidtestnet</code>)</h3>
<ul>
<li><p>It was recently deployed.</p>
</li>
<li><p>There is no pegging, so if you need coins you can use the official faucet here: https://liquidtestnet.com/faucet.</p>
</li>
<li><p>Like in production, the block time is 1 minute.</p>
</li>
<li><p>To configure your Elements node for it, here are the instructions: https://docs.blockstream.com/liquid/node_setup.html#connecting-to-liquid-testnet</p>
</li>
<li><p>It has an official explorer: https://blockstream.info/liquidtestnet/</p>
</li>
<li><p>Unlike regtest, with testnet is public hence be aware of that.</p>
</li>
<li><p>Also, testnet has an official asset registry as well: https://blockstream.info/liquidtestnet/assets</p>
</li>
</ul>
<blockquote>
<p>That can be helpful to debug issuance and registration of assets, a thing you cannot do with regtest.</p>
</blockquote>
<h3 id="heading-liquid-mainnet-chainliquidv1"><strong>Liquid Mainnet</strong> (<code>chain=liquidv1</code>)</h3>
<ul>
<li><p>The production environment of Liquid.</p>
</li>
<li><p>As mentioned before, the block time is 1 minute, and mainnet Bitcoin can be pegged in and out of it.</p>
</li>
</ul>
<hr />
<h1 id="heading-conclusion">🎇 Conclusion</h1>
<p>With this knowledge, you should have enough to get started to work on Liquid.</p>
<p>To sum up, here are my advice, if you are willing to:</p>
<ul>
<li><p><strong>add payment in L-BTC or another Liquid asset on your e-commerce website</strong>, look at BTCPay and WooCommerce with the Liquid+ plugin: https://github.com/ndeet/liquid-assets-for-woocommerce</p>
</li>
<li><p><strong>create a Liquid wallet</strong>, you can either look at the <a target="_blank" href="https://github.com/vulpemventures/ldk">LDK</a> made in TypeScript so good for web apps, or <a target="_blank" href="https://github.com/Blockstream/gdk/">GDK</a> made in C/C++ good for desktop or native apps but also has wrappers for Java, Python, and Swift,</p>
</li>
<li><p><strong>issue an asset</strong> (either NFT or fungible tokens too), you can look at either <a target="_blank" href="https://blockstream.com/amp/">Blockstream AMP</a> or build a custom solution with <a target="_blank" href="https://github.com/vulpemventures/liquidjs-lib">liquidjs</a> or <a target="_blank" href="https://github.com/vulpemventures/go-elements">go-elements</a></p>
</li>
<li><p><strong>create an NFT trading platform</strong>, you can fork off <a target="_blank" href="https://github.com/liquidnft/lnft/">Raretoshi</a></p>
</li>
<li><p><strong>create a SWAP/DEFI platform</strong>, look at coinos open source projects: https://github.com/coinos/.</p>
</li>
</ul>
<p>And to go to deeper in the rabbit hole, you can start searching on these subjects:</p>
<ul>
<li><p>Multisignature wallets</p>
</li>
<li><p>Taproot</p>
</li>
<li><p>Partially signed transactions</p>
</li>
<li><p>Atomic swap</p>
</li>
</ul>
<p>Have fun!</p>
]]></content:encoded></item><item><title><![CDATA[On how to write a technical blog]]></title><description><![CDATA[How to pick a subject?
🐦🐦🪨 Kill two birds with one stone.
Pick a subject related to something you are currently working on or something you are willing to learn.
Or 📰 Check the trending topics.
It's ok to lack inspiration. So don't hesitate to lo...]]></description><link>https://sonny.alvesdi.as/on-how-to-write-a-technical-blog</link><guid isPermaLink="true">https://sonny.alvesdi.as/on-how-to-write-a-technical-blog</guid><category><![CDATA[Blogging]]></category><category><![CDATA[blog]]></category><category><![CDATA[Technical writing ]]></category><category><![CDATA[writing]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Sat, 12 Feb 2022 07:13:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644650118135/od5w-aOtk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-how-to-pick-a-subject">How to pick a subject?</h2>
<p><strong>🐦🐦🪨 Kill two birds with one stone.</strong></p>
<p>Pick a subject related to something you are currently working on or something you are willing to learn.</p>
<p>Or <strong>📰 Check the trending topics.</strong></p>
<p>It's ok to lack inspiration. So don't hesitate to look at the trends in your field and share your experience or point of view.</p>
<h2 id="heading-how-to-take-notes">How to take notes?</h2>
<p>There are plenty of solutions:</p>
<ul>
<li><p>Notion</p>
</li>
<li><p>EverNote</p>
</li>
<li><p>OneNote</p>
</li>
<li><p>Simple text files</p>
</li>
<li><p>Notebook</p>
</li>
<li><p>...</p>
</li>
</ul>
<p>You have to try and find the one that suits you the best.</p>
<p>But:</p>
<ul>
<li><p><strong>Write your ideas as soon as you can</strong>, you may forget them,</p>
</li>
<li><p><strong>Don't elaborate on your writing yet</strong>, you want to be quick and work on the writing quality in a later step,</p>
</li>
<li><p><strong>Don't hesitate to use mnemonics</strong> that you know of or even create yours.</p>
</li>
</ul>
<h2 id="heading-how-to-write-the-article-from-my-notes">How to write the article from my notes?</h2>
<p>Again, my suggestion is to use <a target="_blank" href="https://hashnode.com">Hashnode</a></p>
<p>But anyway in general on most platforms nowadays you need to write in <a target="_blank" href="https://www.markdownguide.org/">Markdown</a> so get used to it.</p>
<p>Then based on your notes, write the first draft on your platform of choice.</p>
<p>But <strong>don't spend hours on it</strong>. Give you time constraints. Timebox the time you spend on it.</p>
<p>While writing:</p>
<ul>
<li><p><strong>If you realize you lack some matter for the content</strong>, go get that matter and come back to your draft later.</p>
</li>
<li><p><strong>If you realize you have too much to say on the subject</strong>, don't hesitate to split your article into multiple ones. It'll be easier to read. Unless you are writing a complete guide on a subject, I would not recommend a long article.</p>
</li>
</ul>
<h2 id="heading-ok-i-wrote-my-article-i-click-on-publish-now">Ok I wrote my article, I click on publish now?</h2>
<p><strong>No, please don't do that, yet!</strong></p>
<p>🧹It's time to clean up your article! Here is the recipe:</p>
<ol>
<li><p>https://hemingwayapp.com/ Copy-paste your contents and fix it according to the feedback. As a thumb rule at the same time, try to remove 15% of your writing. The shorter the better for your reader.</p>
</li>
<li><p>https://app.grammarly.com/ Copy-paste your article into a Grammarly document and fix all the left grammar issues.</p>
</li>
<li><p>(Optional) Get a friend or colleague to read your article and give you feedback.</p>
</li>
</ol>
<p>Alright, remember that <strong>you don't have to get the best score in hemingwayapp, but fixing all the grammar issues is a must.</strong></p>
<h2 id="heading-ok-i-click-publish-now">OK, I click publish now?</h2>
<p>Wait! do you have a cover image 🖼️? No? 🤦</p>
<p>My advice here is:</p>
<ul>
<li><p><a target="_blank" href="canva.com">canva.com</a>, it's super easy and free to create a cover image with clear titles</p>
</li>
<li><p>or <a target="_blank" href="unsplash.com">unsplash.com</a>, it's a free website of stock photos so no titles over but good enough to illustrate an article.</p>
</li>
</ul>
<p>So up to you, but obviously the more explicit is your picture about your article the better!</p>
<p><strong>The last thing is the tags for your article.</strong></p>
<p>I would suggest using a mix of trending tags and less trending ones.</p>
<p>You will take profit from the visibility the trending ones will offer you. And profit from the niche audience of the less trending ones.</p>
<h2 id="heading-click-on-publish-now">Click on publish now!</h2>
<p><strong>Congrats! You published an article to the community!</strong></p>
<p>Time to share the word on social networks and the internet.</p>
<p>Also, <strong>🪴 don't hesitate to garden your article</strong>. Things may evolve, you may find better ways, change opinions, etc. So come back to your article and rework it.</p>
]]></content:encoded></item><item><title><![CDATA[Finding a job is easy?]]></title><description><![CDATA[Since childhood, I longed for working on video games. When we move to China with my wife, I thought it was a good time to try to land a job in the industry!
So, 6 months before actually moving to China, I started my new job search. I sent CVs and app...]]></description><link>https://sonny.alvesdi.as/finding-a-job-is-easy</link><guid isPermaLink="true">https://sonny.alvesdi.as/finding-a-job-is-easy</guid><category><![CDATA[job search]]></category><category><![CDATA[interview]]></category><category><![CDATA[internships]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[jobs]]></category><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Tue, 01 Feb 2022 07:22:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/6ie6OjshvWg/upload/01d308d4d36f97abb579e2a59e7338c7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p> Since childhood, I longed for working on video games. When we move to China with my wife, I thought it was a good time to try to land a job in the industry!</p>
<p>So, 6 months before actually moving to China, I started my new job search. I sent CVs and application letters to tens of companies. I got only got very few responses and all negatives.</p>
<p>By the time, we were actually moving to China, I still had no job. Meaning also not a long-stay visa for me... Time was clocking.</p>
<p>Once in China, I continued to apply daily. I certainly felt hopeless several times and started to reconsider things.</p>
<p>While I was starting to consider alimentary jobs, I scheduled a couple of interviews in Shanghai.</p>
<p>This was somehow the last chance for me. If it was not working out, I would go for a backup plan, I was thinking. Time was clocking after all.</p>
<p>I got a clean haircut, shaved, and we booked a cheap hotel in a Shanghai suburb close to the train station for a week. </p>
<p>The first interviews went ok. But even if it was in the gaming industry, it definitely did not match my ambitions. And what I imagined.</p>
<p>But thankfully, the last one went well. It went great, actually. I made a good impression and the company was fascinating. </p>
<p>I got an offer right away that I accepted in the following hour, the interview, I believe. Ending 8 months of research. And allowing me to stay in China long-term!</p>
<p>But after a month and a half or about so, one morning a company meeting was summoned. The suspense didn’t last long. </p>
<p>The meeting was about the news: The game I was working on was canceled. And the team working on it was being laid off (including me).</p>
<p>But somehow I took the news very neutrally. My career in the gaming industry was just starting. And within this short lapse of time, I felt I proved to myself that I was capable of it. </p>
<p>I didn't want to give up on that career I was longing for and that I know I was capable of. </p>
<p>I resumed my job search with that spirit. But one thing was different, I had a foot in the industry. I had an apartment in Shanghai, a related experience, and a network. </p>
<p>Quickly I have been scheduling 7 to 8 interviews in the following week after the news. I was still very excited and formatted to do job research.</p>
<p>After that week full of interviews, I got a couple of offers. At the same time, I grew my network a lot, and even if I were to be laid off again, I knew I could find something else.</p>
<p>Finding a job is not easy! But to make it easier, here are some tips for you readers if you are currently looking for a job:</p>
<ul>
<li><p><strong>Be in the right mindset</strong> <br />
To maximize your luck, you need to show self-confidence, extraversion, energy, organization, and such. If you are introverted like me, that requires some work on yourself upfront.</p>
</li>
<li><p><strong>If you are moving to a new location, do research on the local companies</strong> <br /> 
TBH, I lost quite some time just trying to apply to the companies I knew, or I could think of. While I could have tried to look for more local companies and understand the local ecosystem.</p>
</li>
<li><p><strong>Use or grow your network</strong> <br />
LinkedIn is great for that, or the internet in general. But also with any interview, you get. You can keep in touch with the company and/or the interviewers. A no is rarely definitive.</p>
</li>
<li><p><strong>Come prepared to interview</strong> <br /> 
You need to be the best of yourself, be full of energy, and ambitions. But also research info on the company and the products you may be working on.</p>
</li>
<li><p><strong>Be patient</strong> <br /> 
Especially if you are trying to join a new industry like the gaming industry, you may have to prove yourself. Get related experience as much as you can and build a portfolio and/or list of references.</p>
</li>
</ul>
<p>Good luck to you in your job research!</p>
<hr />
<p>Photo by <a href="https://unsplash.com/@dylandgillis?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Dylan Gillis</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item><item><title><![CDATA[gRPC proto files Best Practices]]></title><description><![CDATA[This article is a mash-up of different sources cited in references and Pixelmatic guidelines aimed to serve as coding and style guides for proto files in the context of gRPC services definitions.
Coding and style guides
In short, the philosophy of th...]]></description><link>https://sonny.alvesdi.as/grpc-proto-files-best-practices</link><guid isPermaLink="true">https://sonny.alvesdi.as/grpc-proto-files-best-practices</guid><dc:creator><![CDATA[Sonny Alves Dias]]></dc:creator><pubDate>Fri, 21 Jan 2022 09:51:45 GMT</pubDate><enclosure url="https://img.bloggu.io/ipfs/bafybeiczhw5wtcyt2kltpzrzbaoxui4kdupoazfnhb5e356lqh4eddfsra" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article is a mash-up of different sources cited in references and Pixelmatic guidelines aimed to serve as coding and style guides for proto files in the context of gRPC services definitions.</p>
<h2 id="heading-coding-and-style-guides">Coding and style guides</h2>
<p>In short, the philosophy of the guides is:</p>
<ul>
<li><p><strong>Be consistent</strong></p>
</li>
<li><p><strong>Reuse the well-known types from Google</strong></p>
</li>
<li><p><strong>But keep separation as needed to avoid breaking changes</strong></p>
</li>
</ul>
<h3 id="heading-standard-file-formatting">Standard file formatting</h3>
<ul>
<li><p>Keep the line length to 80 characters.</p>
</li>
<li><p>Prefer the use of double quotes for strings.</p>
</li>
</ul>
<h3 id="heading-file-structure">File structure</h3>
<p>Files should be named <code>lower_snake_case.proto</code></p>
<p>All files should be ordered in the following manner:</p>
<ol>
<li><p>License header (if applicable)</p>
</li>
<li><p>File overview</p>
</li>
<li><p>Syntax</p>
</li>
<li><p>Package</p>
</li>
<li><p>Imports (sorted)</p>
</li>
<li><p>File options</p>
</li>
<li><p>Service (1 service per file)</p>
</li>
<li><p>Messages (sorted in the same order of the RPCs and grouped under a comment<code>// region $RPCNAME</code>)</p>
</li>
</ol>
<pre><code class="lang-bash">service Foo {
    rpc Bar(BarRequest) returns (BarResponse);
}

// region Bar
    message BarRequest {
        // ...
    }

    message BarResponse {
        // ...
    }
</code></pre>
<p><em>Note:</em> <code>// region</code> comments are collapsible in Visual Code.</p>
<h3 id="heading-packages">Packages</h3>
<p>Package names should be in lowercase. Package names should have unique names based on the project name and possibly based on the path of the file containing the protocol buffer type definitions.</p>
<h3 id="heading-message-and-field-names">Message and field names</h3>
<p>Use CamelCase (with an initial capital) for message names – for example, <code>SongServerRequest</code>. Use underscore_separated_names for field names (including oneof field and extension names) – for example, <code>song_name</code>.</p>
<pre><code class="lang-bash">message SongServerRequest {
  optional string song_name = 1;
}
</code></pre>
<p>Using this naming convention for field names gives you accessors like the following:</p>
<pre><code class="lang-bash">C++:
  const string&amp; <span class="hljs-function"><span class="hljs-title">song_name</span></span>() { ... }
  void set_song_name(const string&amp; x) { ... }

Java:
  public String <span class="hljs-function"><span class="hljs-title">getSongName</span></span>() { ... }
  public Builder setSongName(String v) { ... }
</code></pre>
<p>If your field name contains a number, the number should appear after the letter instead of after the underscore. For example, use <code>song_name1</code> instead of <code>song_name_1</code></p>
<h3 id="heading-optional-fields"><strong>Optional fields</strong></h3>
<p>Consider the following proto3 message which defines the field <code>bar</code>:</p>
<pre><code class="lang-bash">*message* Foo {  
    int32 bar = 1; 
}
</code></pre>
<p>With this definition, it is impossible to check whether <code>bar</code> has been set to 0 or if no value has been set since the default value of <code>int32</code> fields is 0.</p>
<p>To allow you to make the difference, use:</p>
<pre><code class="lang-bash">message Foo {
  optional int32 bar = 1;
}
</code></pre>
<p>This exposes <code>hasBar()</code> and <code>clearBar()</code> (depending on the language) methods in the generated code.</p>
<h3 id="heading-repeated-fields">Repeated fields</h3>
<p>Use pluralized names for repeated fields.</p>
<pre><code class="lang-bash">  repeated string keys = 1;
  ...
  repeated MyMessage accounts = 17;
</code></pre>
<h3 id="heading-oneof"><strong>Oneof</strong></h3>
<p>Oneof is a wonderful example where a protobuf language feature helps to make gRPC APIs more intuitive. As an example, imagine we have a service method where users are able to change their profile picture, either from an URL or by uploading their own (small) image. Instead of doing this</p>
<pre><code class="lang-bash">// Either <span class="hljs-built_in">set</span> image_url or image_data. Setting both will result <span class="hljs-keyword">in</span> an error.
message ChangeProfilePictureRequest {
  string image_url = 1;
  bytes image_data = 2;
}
</code></pre>
<p>we can define the desired behavior directly into the message with oneof</p>
<pre><code class="lang-bash">message ChangeProfilePictureRequest {
  oneof image {
    string url = 1;
    bytes data = 2;
  }
}
</code></pre>
<p>Not only is that much clearer for API consumers, but it is also easier to check which field has been set in the generated code. Keep in mind that oneof also allows that none of the fields has been set, meaning there is no need to introduce a separate <code>none</code> field if the oneof should be optional.</p>
<h3 id="heading-flexible-data">Flexible Data</h3>
<p>If you do not know in advance the nature of the data you are going to receive from your consumer, we suggest you use the well know type Struct. For example:</p>
<pre><code class="lang-bash">message StructTest {
  google.protobuf.Struct data = 1;
}
</code></pre>
<h3 id="heading-enums">Enums</h3>
<p>Use CamelCase (with an initial capital) for enum type names and CAPITALS_WITH_UNDERSCORES for value names:</p>
<pre><code class="lang-bash">enum FooBar {
  FOO_BAR_UNSPECIFIED = 0;
  FOO_BAR_FIRST_VALUE = 1;
  FOO_BAR_SECOND_VALUE = 2;
}
</code></pre>
<ul>
<li><p>Each enum value should end with a semicolon, not a comma. Prefer prefixing enum values instead of surrounding them in an enclosing message. The zero value enum should have the suffix <code>UNSPECIFIED</code>.</p>
</li>
<li><p>Note that names of enum entries must be unique in the whole package. Defining a second completely unrelated enum with an entry existing in the first will result in an error message because of how enums in C and C++ are implemented. To avoid this, prefix the enum entries with the enum name. Some code generators (ex. for C#) will remove these prefixes automatically so that the resulting code looks "clean" again.</p>
</li>
</ul>
<h3 id="heading-services">Services</h3>
<p>If your <code>.proto</code> defines an RPC service, you should use CamelCase (with an initial capital) for both the service name and any RPC method names:</p>
<pre><code class="lang-bash">service FooService {
  rpc GetSomething(GetSomethingRequest) returns (GetSomethingResponse);
  rpc ListSomething(ListSomethingRequest) returns (ListSomethingResponse);
}
</code></pre>
<h3 id="heading-separate-request-and-response-messages"><strong>Separate request and response messages</strong></h3>
<p>We recommend that you create a separate message for each request and response. Name them <code>{MethodName}Request</code> and <code>{MethodName}Reponse</code>. This allows you to modify request and response messages for a single service method without introducing accidental changes to other methods. It is tempting to re-use messages and simply ignore fields that aren't needed. With time, this will result in a mess, since it isn't obvious what the API expects. Exceptions to this rule are usually made when returning a single, well-defined entity or when returning an empty message.</p>
<pre><code class="lang-bash">service BookService {
  rpc CreateBook(Book) returns (Book); // don<span class="hljs-string">'t do this
  rpc CreateBook(Book) returns (google.protobuf.Empty); // instead do this
  rpc ListBooks(ListBooksRequest) returns (ListBooksResponse); // this is OK
  rpc GetBook(GetBookRequest) returns (Book); // this is also OK
  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty); // this is also OK
}</span>
</code></pre>
<h3 id="heading-use-the-error-system">Use the error system</h3>
<p>Do not return a simple confirmation to an endpoint that does not need to return any other data, use <code>google.protobuf.Empty</code> and trigger an error if needed.</p>
<pre><code class="lang-bash">// Don<span class="hljs-string">'t
service BookService {
  rpc DeleteBook(DeleteBookRequest) returns (DeleteBookResponse); 
}

message DeleteBookResponse {
  bool deleted = 1;
}

// Do 
service BookService {
  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty); 
}</span>
</code></pre>
<h3 id="heading-dont-reinvent-the-wheel">Don’t reinvent the wheel</h3>
<p>Use and abuse of the well-known types:</p>
<p><a target="_blank" href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf">https://developers.google.com/protocol-buffers/docs/reference/google.protobuf</a></p>
<p>Examples:</p>
<ul>
<li><p>The empty message is already defined as <code>google.protobuf.Empty</code>, so it doesn't make sense to define yet another empty message.</p>
</li>
<li><p>Don’t try to redefine timestamp, there’s an existing type for it: <a target="_blank" href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#timestamp">https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#timestamp</a></p>
</li>
<li><p>...</p>
</li>
</ul>
<h3 id="heading-dont-have-one-field-in-a-struct-influence-the-meaning-of-another"><strong>Don’t have one field in a struct influence the meaning of another</strong></h3>
<p>Protocol buffer messages usually have multiple fields. These fields should always be independent of each other — you shouldn’t have one field influence the semantic meaning of another.</p>
<pre><code class="lang-bash">// don<span class="hljs-string">'t do this!
message Foo {
  int64 timestamp = 1;
  bool timestampIsCreated; // true means timestamp is created time,
                           // false means that it is updated time</span>
</code></pre>
<p>This causes confusion — the client now needs to have special logic to know how to interpret one field based on another. Instead, use multiple fields, or use the protobuf “oneof” feature.</p>
<pre><code class="lang-bash">// better, but still not ideal because the fields are mutually
// exclusive - only one will be <span class="hljs-built_in">set</span>
message Foo {
  int64 createdTimestamp;
  int64 updatedTimestamp;
}// this is ideal; one will be <span class="hljs-built_in">set</span>, and that is enforced by protobuf
message Foo {
  oneof timestamp {
    int64 created;
    int64 updated;
  }
}
</code></pre>
<h3 id="heading-linting">Linting</h3>
<p>We use protolint to lint the proto files. Please download and install protolint from <a target="_blank" href="https://github.com/yoheimuta/protolint/releases">https://github.com/yoheimuta/protolint/releases</a>.</p>
<p><strong>Git pre-commit hook</strong></p>
<p>You can also enforce protolint to execute automatically before committing code using <a target="_blank" href="https://pre-commit.com/">pre-commit</a>. Install pre-commit, add a file <code>.pre-commit-config.yaml</code>, and add this content to it:</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">repos:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">repo:</span> <span class="hljs-string">https://github.com/yoheimuta/protolint</span>
    <span class="hljs-attr">rev:</span> <span class="hljs-string">master</span>
    <span class="hljs-attr">hooks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">id:</span> <span class="hljs-string">protolint</span>
</code></pre>
<p>Then run: <code>pre-commit install</code> in the repo.</p>
<h2 id="heading-extra-recommendations">Extra recommendations</h2>
<ul>
<li><p>Use CI to automatically double-check if your proto files still compile without error/warnings.</p>
</li>
<li><p>Avoid large messages. gRPC is not designed for that. Details: <a target="_blank" href="https://kreya.app/blog/grpc-best-practices/#large-messages">https://kreya.app/blog/grpc-best-practices/#large-messages</a></p>
</li>
<li><p>Reuse channels. Creating a gRPC channel is a costly process, as it creates a new HTTP/2 connection. Details: <a target="_blank" href="https://kreya.app/blog/grpc-best-practices/#reuse-channels">https://kreya.app/blog/grpc-best-practices/#reuse-channels</a></p>
</li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://developers.google.com/protocol-buffers/docs/style">https://developers.google.com/protocol-buffers/docs/style</a></p>
</li>
<li><p><a target="_blank" href="https://kreya.app/blog/grpc-best-practices/">https://kreya.app/blog/grpc-best-practices/</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@akhaku/protobuf-definition-best-practices-87f281576f31">https://medium.com/@akhaku/protobuf-definition-best-practices-87f281576f31</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>