<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thamara Andrade</title>
    <description>The latest articles on DEV Community by Thamara Andrade (@thamara).</description>
    <link>https://dev.to/thamara</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F219038%2Fe17ca308-bafb-48b2-b1f0-5ddb19f7d49d.jpeg</url>
      <title>DEV Community: Thamara Andrade</title>
      <link>https://dev.to/thamara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thamara"/>
    <language>en</language>
    <item>
      <title>Colorall Game Devlog - Creating a game in one week</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 07 Feb 2022 03:56:56 +0000</pubDate>
      <link>https://dev.to/thamara/colorall-game-devlog-creating-a-game-in-one-week-598a</link>
      <guid>https://dev.to/thamara/colorall-game-devlog-creating-a-game-in-one-week-598a</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr;
&lt;/h2&gt;

&lt;p&gt;I developed a game by myself for the One Minute Game Jam using Godot in just a few days. You can check it and play it online at &lt;a href="https://thamara.itch.io/colorall"&gt;itchi.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it all began
&lt;/h2&gt;

&lt;p&gt;I will not lie that when choosing courses for college, one of the big highlights of computer science was the possibility of becoming a game developer. But soon I found out there were a lot more options out there and I ended up working with software development in the EDA industry, which I really like. In the past years, after spending a lot of my free time playing electronic games, I was getting more and more curious about what it takes to create a game. So I started watching a tutorial here and there, but nothing beyond that.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first Game Jam
&lt;/h3&gt;

&lt;p&gt;So jumping to the end of 2021, a dear friend of mine asked me and some other friends to join him on a &lt;a href="https://en.wikipedia.org/wiki/Game_jam"&gt;Game Jam&lt;/a&gt;, which I had no idea of what it was really. He explained that it was like a "hackathon", to put in words I was more familiar with. During a determined period, you would work on developing a game that would fit some restrictions and themes defined by the Game Jam. It was not required to be a complete and bug-free game, the important thing was to have fun. That was also when he presented me &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt;, a free and open-source game engine, and so, using Godot we developed &lt;a href="https://hamiltonrf.itch.io/bring-ur-glam"&gt;Bring Ur Glam&lt;/a&gt;, a 2D platform/shoot' em up game for the &lt;a href="https://itch.io/jam/game-off-2021"&gt;Game Off 2021&lt;/a&gt;, where the theme was BUG.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DwU9_xzn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/bringurglam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DwU9_xzn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/bringurglam.png" alt="Bring Ur Glam Image" width="880" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was a lot of fun working on this game and I think the result is absolutely beautiful. I got to learn a lot about game development and Godot, understanding the basics of movement, collisions, camera movement, enemy AI, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting back
&lt;/h3&gt;

&lt;p&gt;After the Game Jam, I was like "when is the next one?", but the end of the year was around the corner and lots of other things were happening, so I let go of this possible new hobby. I would still watch occasional videos on Youtube on this subject, but not get up from the bed to do anything concrete.&lt;/p&gt;

&lt;p&gt;A few weeks ago, I opened Godot again for the first time in the year and started doing some experimental things. But, one of my biggest flaws when it comes to personal projects, is that I work hard in the beginning, but when things get to the usual busywork, I get tired and find something else to do. I almost always need someone else with me to get me continuously excited, or need a clear and defined deadline/goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Minute Game Jam
&lt;/h2&gt;

&lt;p&gt;On Sunday, Jan 30th I bumped into &lt;a href=""&gt;this video&lt;/a&gt; from Vimlark, which is one of my favorite creators on the subject of game jams and game development. He was highlighting the upcoming game Jams and there was one starting the next day going up to Feb 5th: the &lt;a href="https://itch.io/jam/one-minute-game-jam-5"&gt;One minute game jam&lt;/a&gt;. The limitation of this jam was not to make a game in one minute but to create a game with gameplay of less than one minute, and a theme that would be released when the jam started. Five days sounded like something I could handle and the time limitation would make me stick to a reduced scope, so I joined it, and this is how it went.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1: Monday, Jan 31st
&lt;/h3&gt;

&lt;p&gt;The jam started at 20h my timezone and theme was "COLORFUL".&lt;/p&gt;

&lt;p&gt;I already had one idea in mind which came to me when I saw the time limitation, but after a few minutes of brainstorming, I could not fit the theme in any way, so I started a new brainstorming session looking for the main concept.&lt;/p&gt;

&lt;p&gt;I thought about something related to chameleons, mixing up colors, metro lines, stained glass, and more. But nothing was really clicking beyond "mixing up colors".&lt;/p&gt;

&lt;p&gt;So I went with it and started thinking about how the game would be, and settled on something like "you are working on selling paints and need the get the raw material, mix it, and deliver paintings". The way you would get the raw material would be through a match-3-like game, in which, when matching 3 or more of the same color you would get number as paint material, but could also switch two non-matching tiles of primary colors to make secondary colors. You would get a minute and be scored on the number of paintings completed.&lt;/p&gt;

&lt;p&gt;As I would only be able to work on this game at night, I begin with the implementation right away. The first thing I needed was the basics for a match 3 game, that is tiles, a grid to put the tiles, and the ability to change tiles placement. That was fairly easy to set up as I found out days before that Godot's tilemap is capable of returning the real position from a tile numbering and vice-versa, so no complex math was required.&lt;/p&gt;

&lt;p&gt;At the end of the time I had to work on the game on Monday the really basic blocks for everything was done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 2: Tuesday, Feb 1st
&lt;/h3&gt;

&lt;p&gt;On Tuesday I worked on the system to exchange pieces placement, matching them, registering matches and refilling the board, and also the painting orders. That went kind of smooth, especially after finding &lt;a href="https://www.youtube.com/watch?v=YhykrMFHOV4&amp;amp;list=PL4vbr3u7UKWqwQlvwvgNcgDL1p_3hcNn2&amp;amp;ab_channel=MisterTaftCreates"&gt;this playlist&lt;/a&gt; by Mister Taft Creates where they implement a match 3 game in Godot.&lt;/p&gt;

&lt;p&gt;After around 2 days, 8-ish hours of development here's what I had:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl-aY3au--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/match3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vl-aY3au--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/match3.gif" alt="First version" width="880" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it was... terrible! I'm not even talking about the colors, lack of beautification, or anything like this. The gameplay was bad. It was really horrible to focus on which colors I needed to match in order to complete a painting. There was no fun in it. My idea was bad and definitely was not working for a game that should be played in one minute.&lt;/p&gt;

&lt;p&gt;I was frustrated and started thinking about how to fix it. The more I tried to adjust it and make it be fun, the more I got sad about everything. Maybe I have bitten more than I could chew entering a game jam by myself.&lt;/p&gt;

&lt;p&gt;That's when I took the best decision for this jam: I would abandon everything and start fresh. If I couldn't make it in time, that was ok. I was already in a state of mind where I wouldn't submit anything. If something good came out, profit, otherwise, learning opportunity.&lt;/p&gt;

&lt;p&gt;Looking back, I see that I was dealing with the &lt;a href="https://en.wikipedia.org/wiki/Sunk_cost#Fallacy_effect"&gt;sunk cost fallacy effect&lt;/a&gt;, where you had a hard time abandoning something just because you already spend time and energy on it. This unfortunately is something that I see myself doing many times, from continuing a show I'm not liking until the end just because I had already spent so much time on it, to keeping projects on the pipeline because it's 90% complete, even though I don't see it being that helpful anymore.&lt;/p&gt;

&lt;p&gt;I went back to my brainstorm document (aka a piece of paper with lots of scribbles) and spend a few minutes just staring at it. That's when it hit me, a game where you have a grid of colored tiles, and, starting at a given point, you can change the color of the tile to match one of its neighbors. Somewhere in the past 1 or 2 years, I had played something similar, but in there, there was a limitation of steps you could take, so you would need to be very thoughtful when choosing a color. But I thought that it could be fun to recreate this, but limiting the time, allowing the player to win more often.&lt;/p&gt;

&lt;p&gt;I closed the work on Tuesday with this idea, and the best thing is, I already had the grid. I didn't need all the features to exchange tiles, only be able to change a tile color, which I already had too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 3: Wednesday, Feb 2nd
&lt;/h3&gt;

&lt;p&gt;As mentioned, I already had the basic building blocks for the new idea, it was a matter of cleaning up the code and adjusting some of the functions to work like the flood fill instead of matching 3 or more tiles of a given color.&lt;/p&gt;

&lt;p&gt;In a matter of fewer than 2 hours, I already had something that was already working but to have a more realistic feel for the game I started working on a few visual elements, mainly the colors and how the user would select colors.&lt;/p&gt;

&lt;p&gt;I'm not that good with choosing colors that would look cohesive, especially because I needed 8 different colors. So I headed to &lt;a href="https://lospec.com/"&gt;Lospec&lt;/a&gt; and selected a &lt;a href="https://lospec.com/palette-list/dibbles"&gt;palette&lt;/a&gt; I liked. This is a great resource if you need some help choosing colors for a game or pretty much for anything. The site has palette lists that are focused on pixel art, but really, you can do anything with that.  Now it was time to work on the means of changing colors in-game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ityzy9m_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/color_selection.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ityzy9m_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/color_selection.png" alt="Color selection" width="428" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left, the initial idea, just a plan small grid with the colors. But this showed up to be not that great. If the player wanted to go from dark blue on one corner to red on the other corner, the mouse would need to move quite a lot and as time is a precious item here, I went with a color wheel, illustrated in the right, this way, the mouse needs to move less between colors. I ended up liking so much this color wheel that I make it the icon for the game, as well as included it in the name of the game.&lt;/p&gt;

&lt;p&gt;After throwing some fonts and a timer, the game was already playable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OzbfmvRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OzbfmvRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v2.gif" alt="Coloral version 1" width="880" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I send it to a few friends and collected feedback. The feedbacks were great, of course, it was still missing a lot of UI elements as well as sound work, but helped me validate the idea. They also mentioned that it was not completely clear what they needed to do, even though I had sent a brief explanation. So it was clear that the game needed a tutorial of some sort, as well as a better indication that you should use the wheel to change colors, not clicking on the tiles.&lt;/p&gt;

&lt;p&gt;But before working on this feedback that was still something bothering me: a player could just start clicking mindlessly on the colors and get a high score, pretty much making this game a "let's see how fast you can click", which was not the idea. To try to force a game approach close to what I wanted, that is, you have to think a bit about what you are doing, I changed to score to be not only the number of squares you complete in the time but to be a function of the number of squares completed minus the number of clicks it takes you, all of this multiplied by the time left. This way the player would be rewarded for being fast, but still needed to think about their moves.&lt;/p&gt;

&lt;p&gt;This wasn't still enough, as in the end, in a grid of 10x10 for example, you could still go crazy clicking without thinking and finishing quickly. To solve this I added a click cooldown of 1 second. After this, I tried to break the gameplay I had in mind, and, although theoretically, the player can still not think about what you are doing, most times when I tried to play like this, I end up losing the game, so, this seems to work well.&lt;/p&gt;

&lt;p&gt;I finished the day with the main part of the game implemented and ready and had already started working on the main menu and being able to go from it to the game and back. That was also when I settled on the name "Colorall". This was actually my placeholder name, but it started growing on me and I decided to go with it.&lt;/p&gt;

&lt;p&gt;Fun fact: a few hours before submitting the game after even with a mostly complete page for the game, I almost changed its name to "Blob", as I constantly saw myself using this word to refer to the initial group of pieces you control. But I realized it would be too much work to change everything, from screenshots to the game itself, and let it as Colorall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 4: Thursday, Feb 3rd
&lt;/h3&gt;

&lt;p&gt;On Thursday it was a lot of busywork. There were a lot of constants hard-coded in the engine and I wanted to make it all parametrized so I could easily reuse everything for different levels. It was definitively worth doing so.&lt;/p&gt;

&lt;p&gt;Once I had the main game scene parametrized to the width, height, and some other things, it was just a matter of instantiating the scene with different values and I could have an easy, medium, and hard mode. In practice, the only change between those are the width and height and click cooldown. The easy mode is 7x7, the medium is 12x9 and 14x11. The easy and medium modes have a cooldown of 1 second, and the hard one is down to 0.5 seconds, as it contains ~150 tiles (I tried with 1 second too, but it was just too damn hard).&lt;/p&gt;

&lt;p&gt;Initially, the levels would also vary in the number of colors available, but I decided against it just because I would need to introduce a lot of other features just to make this possible. Changing the dimensions of the grid already added enough playing variety.&lt;/p&gt;

&lt;p&gt;I also throw a new level selection screen, worked on the music and effects, as well as fixed some bugs that were lingering.&lt;/p&gt;

&lt;p&gt;The main feature added on day 4 was the ability to save high scores and notify when a user hit them. The idea is that I have a GameManagere singleton that is initialized before the game and is responsible for loading the player's high score. This component is also notified when a game is finished to save the score (if it's a new high score).&lt;/p&gt;

&lt;p&gt;On Thursday's I always meet with some friends over zoom where we play board games online and chat. I used this opportunity to get more feedback. Again, the feedbacks were great! They really liked the game but pointed out that it was still hard to understand what should be done. I took note of everything and started to incorporate the solutions while still on the call with them. I could try a few things, share the screen and get more feedback. To my friends: thanks again! And sorry me not joining as many board games as usual.&lt;/p&gt;

&lt;p&gt;As I'm used to sleeping late on Thursdays' I was able to progress a lot and finished the night with a game that was already complete. It had everything I wanted at that point, including a simple tutorial. It stored scores, had some nice sound effects as well as all necessary screens. I could submit the game at that point, which really surprised me. I was sure I would need to pull an all-nighter from Friday to Saturday, but instead, I was able to develop a full game which I was proud of in about 2 days! Of course, with so much time left in my hands, I started to scope in a lot of other things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 5: Friday, Feb 4th
&lt;/h3&gt;

&lt;p&gt;On Friday I basically worked on two things: fixing the bugs and an achievement system. I never thought about how these systems are implemented, so I started researching and watching/reading how other people do this. Turns out, it was much simpler than I thought, at least a system that worked for me in this game.&lt;/p&gt;

&lt;p&gt;The way I did was to create a scene that would be an overlay of my game scene (remembering that all levels of difficulty use the same game level). This achievement scene contains just one small container that, when an achievement is unlocked, it will show on the corner. This actual "new achievement" object is set to be destroyed a few seconds after it's added to the scene. I also added some code so that at the most, one new achievement unlocked is shown, this way there's no risk of the player facing a wall of notifications.&lt;/p&gt;

&lt;p&gt;The next challenging part of the achievements (beyond writing achievements - like I don't know why but this is really hard to me) is how to display and store them. Storing was actually easier, because, as metadata, I could handle and modify it as I wished, but actually showing it to the user was a different case.&lt;/p&gt;

&lt;p&gt;I wasn't completely sure of how many and which were the achievements I wanted, so I wanted to work on something that could be extendable and not hardcoded. It allowed me to mess with the Control nodes of Godot, something that until this point I never really understood.&lt;/p&gt;

&lt;p&gt;In the end, after some experimentation, I could create something that I was proud of, like, really proud of. It's not the most modular thing, but it works very well. When adding a new achievement I just needed to make sure to add an object with the achievement id and register that id in the GameManager. The id is later used to query the important things of the achievement like the name, description, and of course if the player achieved it or not.&lt;/p&gt;

&lt;p&gt;In the final version of the game I selected 5 achievements that I found fun and interesting, as well as achievable considering a short game session:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Soooo close!: Complete a level with less than 1 second remaining&lt;/li&gt;
&lt;li&gt;Full cycle: Complete a level where the last color is the same as the color of your starting blob&lt;/li&gt;
&lt;li&gt;Beat the Dev: Get a score higher than the developer of the game (Easy: 1370, Medium: 2411, Hard: 2532).&lt;/li&gt;
&lt;li&gt;Saving much?!: Complete a level using at least one color only up to one time.&lt;/li&gt;
&lt;li&gt;10x everywhere!: Play a level at least 10 times. Winning is good, but playing is what counts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the time of writing this, I actually realized there's was a typo in one of the descriptions for the achievement. Hopefully, nobody will notice. Ooops&lt;/p&gt;

&lt;p&gt;What I call GameManager, that is the game manager is also responsible for triggering the achievement notification as well as storing everything. This required some cleanups and also pointed to some bugs in the game. Those bugs were not impacting the game in a bad way, but definitely impacted the computation of the achievements. All the bugs identified were fixed, but most liked there are still many bugs out there. After all, this was developed in a few days.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 6: Saturday, Feb 5th
&lt;/h3&gt;

&lt;p&gt;In all honesty, many of what I'll describe later actually took place during the night between Friday and Saturday. I'm usually most productive at night. I get in the zone and just go. This, plus a dentist appointment early in the afternoon of Saturday made me want to finish everything in the dawn of Saturday.&lt;/p&gt;

&lt;p&gt;Everything was actually ready-ish. There were some final touches on the achievement system as well as some minutes playing and replaying the game over and over again. A few bugs were caught and fixed and I started to gather screenshots and well as put together the page on itch.io. I wanted a very nice page as I think games with nice and clear pages receive more attention.&lt;/p&gt;

&lt;p&gt;In this last mile, I created a lot of releases as I was constantly noticing things that were incorrect or could be better. The major bug found in this phase was that I noticed that I had left all my debug key binds on. While developing, especially the achievement system, I had added code that would trigger specific achievements, just to test everything without needing to actually achieve them, and all these were in the release still. Luckily, there was still time and I removed the debug code and nobody even saw it.&lt;/p&gt;

&lt;p&gt;There was just one last feature I wanted to add. When I settled for a game with uses colored tiles, I knew it was not really accessible for color blind people, but I thought it was a compromise I had to make as it probably would take time to improve the game. But there it was, I still had time, so, why not?&lt;/p&gt;

&lt;p&gt;To my happy surprise, because I was really using two sprites, one for the tiles and the other for the color wheel, it was easy to create another version of these with symbols on top. So I jumped into Inkspace, throw some random shapes, imported them into Godot, and with a global variable that stores if it's on colorblind mode or not, made the tile and color wheel components select the correct resource.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gXvZJJOR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gXvZJJOR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v4.gif" alt="Colorall color blind mode" width="880" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do know that there are still many elements that make the game not accessible for many people and even related to color blindness, I may have done better, but I don't think I'm educated enough in this matter to make better decisions yet.&lt;/p&gt;

&lt;p&gt;And at around 7 AM on Saturday, I published the game and submitted it to the game jam! Closed the notebook and went to bed. I haven't slept yet. After 5-ish hours of sleep, I woke up to my appointment, and while Uber-ing there I checked the game page and there were already some comments of people liking the game, it got me so excited I even forgot I was sleepy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n6aJFck8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n6aJFck8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thamara.dev/assets/img/posts/colorall_v3.gif" alt="Final colorall version" width="880" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  After hours
&lt;/h3&gt;

&lt;p&gt;After the Game Jam finishes, everybody who submitted a game can play and rate the games. I'm currently slowly taking in every game submitted and there are some really nice and interesting games! It's really cool to see how other people interpreted the theme and limitations and created unique and cool games.&lt;/p&gt;

&lt;p&gt;The final rates will only be available in a few days, but the comments on Colorall have been absolutely incredible. People are complementing the game, the graphics, the simplicity, yet with great execution. A user has even said that "I would download this on the app store for my phone right now.". I'm feeling very fulfilled and really glad that I didn't give up on day 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final remarks
&lt;/h2&gt;

&lt;p&gt;I am very happy with the result and definitely, it was a cool challenge to take on. For sure I'll be doing that again but most likely not in a jam that runs basically only on weekdays. I worked every night of this week on the game and by the end of the week I was so tired, I spend most of the weekend sleeping.&lt;/p&gt;

&lt;p&gt;I missed most of the game night with my friends as well as got set up in some other activities I usually do during the week. But Game Jams that would span weekends would totally be doable.&lt;/p&gt;

&lt;p&gt;If you want to check the game, it's available in &lt;a href="https://thamara.itch.io/colorall"&gt;itch.io&lt;/a&gt;, and you can play directly in the browser, or download it and play on a Windows machine for a better experience. The code is also available on &lt;a href="https://github.com/thamara/colorall"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And thanks one more time to Hamilton, not only for the feedback on this game but for presenting me the world of game development, game jams, and Godot, as well as Bárbara, Arthur, and Daniel who played the game and provided feedback. You are great! &lt;strong&gt;&amp;lt;3&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
    </item>
    <item>
      <title>Guessing better in Wordle using Python</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Fri, 07 Jan 2022 14:34:05 +0000</pubDate>
      <link>https://dev.to/thamara/guessing-better-in-wordle-using-python-4oo6</link>
      <guid>https://dev.to/thamara/guessing-better-in-wordle-using-python-4oo6</guid>
      <description>&lt;p&gt;It's a new year and usually, people tend to make goals of working out, getting more organized, and leaving addictions, and I'm no different. But to my surprise, I started the year with a new addiction I don't think I'll plan to quit so soon: &lt;a href="https://www.powerlanguage.co.uk/wordle/" rel="noopener noreferrer"&gt;Wordle&lt;/a&gt;, that game by &lt;a href="https://twitter.com/powerlanguish" rel="noopener noreferrer"&gt;Josh Wardle (@powerlanguish)&lt;/a&gt; which was even featured in the &lt;a href="https://www.nytimes.com/2021/11/24/at-home/newsletter.html" rel="noopener noreferrer"&gt;NY Times&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The idea of the game is pretty simple, yet, very interesting. You have 6 tries on guessing a word per day. On each guess, the game will tell which letters are in the word - in the correct spot and somewhere else in the word - and if a letter is not in the word at all. With this information you try more times, getting more information on each try, up to the 6th or earlier guess where you guesses correctly or you didn't get it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fwordle2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fwordle2.png" alt="Wordle game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you have only 6 guesses per day, this can become very serious. In the past few days, I spent about 15 or more minutes trying to solve this. With many of these minutes it was just me idling, thinking of 5 letter words in English.&lt;/p&gt;

&lt;p&gt;But, being the curious person I am, I started wondering what would be the best approach for this. Many theories came from friends and the internet: starting with a specific word, trying to use words with non-repeating letters (even if you are already sure of a letter in a specific place), and more. But, are they right?&lt;/p&gt;

&lt;p&gt;So I decided to take on this little challenge of getting these answers using code, more specifically, my favorite language for this kind of thing, Python. But looking back, as I wanted to test different scenarios multiple times, I should've tried using C++.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;From this point on, I'll share pieces of code and information that can potentially be used for cheating. My idea with this was never to cheat in any way when playing (I mean, what's the point?). I haven't used any of the key information I got for this end, and I highly recommend you not spoil the fun either.&lt;/p&gt;

&lt;p&gt;In case you want to play with this, I'll be making all the code available on GitHub (link to come soon - &lt;a href="https://twitter.com/thamyk" rel="noopener noreferrer"&gt;ping me on Twitter&lt;/a&gt; if the link isn't here yet and I'll let you know when it's ready - still cleaning it up a bit).&lt;/p&gt;

&lt;p&gt;I'm by no means the first to think of writing a piece of code that could solve or aid the game. After having the idea some posts started to pop up on my Twitter feed, but I didn't want to get "contaminated" and decided to bookmark those for later. After playing a lot with my solution on Python I went ahead to look at the other's take on this. Tyler Glaeil wrote a really cool article on the &lt;a href="https://medium.com/@tglaiel/the-mathematically-optimal-first-guess-in-wordle-cbcb03c19b0a" rel="noopener noreferrer"&gt;mathematically optimal first guess&lt;/a&gt;, Rodrigo Serrão wrote a &lt;a href="https://mathspp.com/blog/solving-wordle-with-python" rel="noopener noreferrer"&gt;solver in python&lt;/a&gt; and shared it on their site, and Bertrand Fan also decided on answering what's &lt;a href="https://bert.org/2021/11/24/the-best-starting-word-in-wordle/" rel="noopener noreferrer"&gt;the best starting word in Wordle&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Word database
&lt;/h2&gt;

&lt;p&gt;The first thing I did was to find a database of English words. I started with the words from &lt;a href="https://github.com/dwyl/english-words" rel="noopener noreferrer"&gt;swyl/english-words&lt;/a&gt; repository. Later, when I read &lt;a href="https://bert.org/2021/11/24/the-best-starting-word-in-wordle/" rel="noopener noreferrer"&gt;Bertrand's post&lt;/a&gt;, I realized I could actually use the words from the game source code. The results I'll show here are considering the game words, but initially, I only used the words from the first source I mentioned here, which were more than enough for playing with and yield very similar results to the Wordle words.&lt;/p&gt;

&lt;p&gt;The database is made by 2315 possible words for each day, with other 10657 words that are less common and are accepted as guesses. So, a total of 12972 words are to be used in guesses and in my experiments.&lt;/p&gt;

&lt;p&gt;For all effects, the results I'm showing here are running the tests 1000 times, keeping the same secret words in between experiments, meaning I'll test 1000 different words in each approach and will compare them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the game itself
&lt;/h2&gt;

&lt;p&gt;With the word database, I started to implement the game. As the game is simple, so was the code that plays it. The basic structure is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_all_words&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_guess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CorrectSpot&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I got it in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number_of_guesses&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tries! The secret word was: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filter_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I start storing all the 5 letter words in an array &lt;code&gt;words&lt;/code&gt;. And then, iterate 6 times picking a random word from &lt;code&gt;words&lt;/code&gt;, calculating the result for this guess, and, if in the result all the letters are in the correct spot, then I know I won. Otherwise, I filter the words on the array with the information I got from the result.&lt;/p&gt;

&lt;p&gt;To represent the result I used an Enum and a simple matcher to calculate the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CorrectSpot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;IncorrectSpot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;NoSpot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_guess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;match_latter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CorrectSpot&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncorrectSpot&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoSpot&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;match_latter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt; &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each letter on the guess word, there's a Result value: A &lt;code&gt;Result.CorrectSpot&lt;/code&gt; if the letter in the specific position in the guess word is the same - in the same position - in the secret word. An &lt;code&gt;Result.IncorrectSpot&lt;/code&gt; if the letter is not in the same place in the guess word, but it's present in the word somewhere else. And &lt;code&gt;Result.NoSpot&lt;/code&gt; if the letter is not present at all in the secret word.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# remove the guess_word from the list of words
&lt;/span&gt;    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# filter by the letters we know aren't in the secret word
&lt;/span&gt;    &lt;span class="n"&gt;forbidden_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoSpot&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;forbidden_letters&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="c1"&gt;# filter by the letters we know are in the secret word, in the correct spot
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CorrectSpot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

    &lt;span class="c1"&gt;# finally, filter by the letters we know should be in the word
&lt;/span&gt;    &lt;span class="n"&gt;existing_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoSpot&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing_letters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;existing_letters&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The filter is very simple. I start by removing the guess word from the &lt;code&gt;words&lt;/code&gt; left. Then, I follow on using the information from the result, that is, removing words that have any letter that was flagged by &lt;code&gt;Result.NoSpot&lt;/code&gt;, removing words that do not have the letters in the specific locations identified by &lt;code&gt;Result.CorrectSpot&lt;/code&gt;, and finally, filtering out the words that don't have any of the letters that we know are in the secret word, tagged by either &lt;code&gt;Result.CorrectSpot&lt;/code&gt; or &lt;code&gt;Result.IncorrectSpot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this, I was left on how to pick my guesses. My first approach was a naive and the simplest solution I could think of: randomly pick a word from the &lt;code&gt;words&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With my naive solution, the program was being able to win the game 49.7% of the time, with an average of 4.1 guesses. On the losing scenarios, I got an average of 1.3 letters in the correct place found. It was kind of ok, but now the real fun begins. What I can do to increase the winning percentage?&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart-ish solution
&lt;/h2&gt;

&lt;p&gt;The first thing I wanted to try was to prefer guesses that didn't have any duplicated letters, trying to have more information on different letters on each guess. If there is no word fitting these criteria, then I would fall back to the naive random solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;smartish_pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this mode, I got 66.7% of wins, with an average of 4.1 guesses. A good improvement from the 49.7% from the naive, but not as I was anticipating. I believe the reason for this is that at the end of my guesses, I was still left with an average of 12 letters in the alphabet as well as many words to try as in the losing scenarios. In the cases where it loses it only knows about 1.2 letters in the correct place. That's why I called it smart-ish, the idea looked good at first, but not that much in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart considering most common letters
&lt;/h2&gt;

&lt;p&gt;To try to improve my implementation, I tried to use the knowledge of the &lt;a href="https://en.wikipedia.org/wiki/Letter_frequency" rel="noopener noreferrer"&gt;most common letters in English&lt;/a&gt;. The idea was to keep the idea of choosing words without repetition of letters, but first, consider words that contained at least 2 of the 8 most common letters in English. If we don't have any words fitting this, then fall back to the Smart-ish solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;words_with_common_letters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# filter words that have at least two of the 8 most common letters
&lt;/span&gt;    &lt;span class="n"&gt;most_common_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;e&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;o&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;i&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
    &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;most_common_letters&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;smartish_pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;smartish_pick_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This improvement barely raised the win porcentage from the previous 66.7% using the Smart-ish solution to 66.9% wins, with an average of 4 guesses to win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weigthing the letters
&lt;/h2&gt;

&lt;p&gt;I still had hoped of using the information on the most common letters so I decided to try this in another way. Still, with the idea of preferring words that don't have duplicated letters, I follow on giving weights for the words. This weight is a simple function of using the frequency of each letter in the alphabet as the value for that letter in a word. For example, the letter E is the most common with a frequency of 13%, so the weight of the letter E is 13. The letter T has a frequency of 9.1%, so its weight in a word is 9.1. And so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weigth_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;
    &lt;span class="n"&gt;words_weigth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most_common_letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;words_weigth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words_weigth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;words_weigth&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words_weigth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;words_with_common_letters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When there was no good option without duplicated letters, I would still try to weight all the remaining words. And, after sorting those, I would choose the one with a higher weight.&lt;/p&gt;

&lt;p&gt;This yield a good result, with 75% of wins, with an average of 3.7 guesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoiding any repetition at first
&lt;/h2&gt;

&lt;p&gt;That's the point where I started talking with friends to understand their approaches. One of them told me they tried to use words that didn't have any letter in common with the previous, even if the previous one gave them some knowledge of the placement or existence of a given letter. So I wanted to try this option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;avoid_repetitions_at_first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tried_words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;forbidden_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tried_words&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;forbidden_letters&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;good_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;
        &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;weigth_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;good_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;weigth_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this, I stored all the previous guesses and removed any words that had any letter that was already used. With some tests, I saw that using this only on the first 3 tries yielded better results. Otherwise, when this is not possible - there are no words matching this - I would use the weighting method.&lt;/p&gt;

&lt;p&gt;With this approach, I got 76% of wins, with an average of 3.8 guesses to find the correct word. Which Is not that different from weighting the letters, but in practice, for a human approach, is much easier to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with a specific word
&lt;/h2&gt;

&lt;p&gt;The last test I wanted to conduct was to see if starting with a specific word would give me better results than any of the previous attempts. This has been the most discussed thing around the game, with some saying that starting with words like "roate", "soare", "orate", or even some words that don't look like words but have a bunch of vowels like "adieu" or "aeons" will give better results. So, I want to put that under a test. I chose to stick to words that actually sound like words because in practice when playing, those are the words I usually try.&lt;/p&gt;

&lt;p&gt;The code for this is basically forcing the first guess, and afterward falling back in the avoid repetition method, as it was the one yielding the best results so far. As I had more than 2300 words to consider, and I wanted to run each test 1000 times, this took ages to run. At this point, I regretted not watching out for performance in the code, but I was already committed and went the lazy way - multiprocessing the code.&lt;/p&gt;

&lt;p&gt;Going by the numbers, the best word (and again, here I'm only considering words that are more common) to start the guesses is "prism", with 83.4% of victories. But other words like "stomp", "crisp", "sport", "blush", among others were still above 82% of victories. The average number of guesses ranged from 3.7 to 3.9. In total, about 110 words being chosen as first words gave it more than 80% of the wins.&lt;/p&gt;

&lt;p&gt;That was very interesting to see because it actually raised the percentage of wins from a previously 76% in many cases, which I was not really expecting to be that different. Also, when checking the lowest scoring words, many words with repeated letters show up, like "queue", "jetty", "woozy", corroborating with the idea of prioritizing words with unique letters. These worst rating words only made about 64% of wins, with an average of 4 guesses.&lt;/p&gt;

&lt;p&gt;The words I found in many of the articles are not considered as real-ish words by the game, in the sense they will never be answers to the daily challenges. But either way, I wanted to see how they would behave, and to my surprise, they did not that great compared to the words I found as the best ones to start. Using the word "roate" as a first guess gave 78.1% of wins, "orate", "adieu", "aeons" had between 77.2% and 77.6%, and "soare" only wins in 74.5% of the times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of attempts
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Naive&lt;/th&gt;
&lt;th&gt;Smart-ish&lt;/th&gt;
&lt;th&gt;Smart with common letters&lt;/th&gt;
&lt;th&gt;Weighting letters&lt;/th&gt;
&lt;th&gt;Avoiding repetitions at first&lt;/th&gt;
&lt;th&gt;Starting with "prism"&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Winning percentage&lt;/td&gt;
&lt;td&gt;49.7&lt;/td&gt;
&lt;td&gt;66.7&lt;/td&gt;
&lt;td&gt;66.9&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;76&lt;/td&gt;
&lt;td&gt;83.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average tries&lt;/td&gt;
&lt;td&gt;4.1&lt;/td&gt;
&lt;td&gt;4.1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3.7&lt;/td&gt;
&lt;td&gt;3.8&lt;/td&gt;
&lt;td&gt;3.8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Final thoughts and (possible) future work
&lt;/h2&gt;

&lt;p&gt;At the end of the day, most approaches here are not practical unless you want to use a computer to solve the challenges which is basically taking out the fun of the game, but regardless, I had a lot of fun playing with the code, trying to tweak the algorithms to reach better results. There's still quite a lot of things I would like to try, for instance, perfecting the guesses to better distribute the possible letters when using an approach like avoiding the repetition and doing a frequency and placement analysis of the letters in the possible 5 letter words instead of using the generic frequency of letters in English. My gut feeling is that with better algorithms I could reach something around 90% or higher.&lt;/p&gt;

&lt;p&gt;Also, recently a &lt;a href="http://term.ooo/" rel="noopener noreferrer"&gt;Wordle version in Brazilian Portuguese&lt;/a&gt; was released and I would like to see if the same approaches for the English version would work as well in Portuguese.&lt;/p&gt;

&lt;p&gt;Based on the not-so-great performance of some of the experiments, I would also consider redoing this in C++, just so I have a bit more room for longer and more expensive computations.&lt;/p&gt;

&lt;p&gt;In a few weeks, given that I will not get tired of the game sooner than this, I also intend on returning to this code to see how much better or worst the algorithms are compared to my non-cheating-human-powered results. So far, for the few words I played, I'm doing much better than my best algorithm here as I haven't got any word wrong, but yes, it's too early to conclude I'm better than my computer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fwordle_result.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fwordle_result.jpeg" alt="My score in wordle, 100%"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you got any ideas on how to improve the performance of the algorithm and would like to share, just shout out on &lt;a href="https://twitter.com/thamyk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Online tools for C++ developers</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 02 Aug 2021 12:54:09 +0000</pubDate>
      <link>https://dev.to/thamara/online-tools-for-c-developers-30ln</link>
      <guid>https://dev.to/thamara/online-tools-for-c-developers-30ln</guid>
      <description>&lt;p&gt;C++ is the main language I use. It's what pays my bills but more than that, is what gives me a lot of joy due to its complexity and powerfulness. But many times when I'm working I miss the ability to do quick tests without having to compile the code or writing auxiliary structures.&lt;/p&gt;

&lt;p&gt;Lucky for me (and for all the C++ developers out there) there are online tools that will ease these tasks. In this post, I'll present some of those tools that I use more frequently and the scenarios where they are the best fit for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn Cpp
&lt;/h2&gt;

&lt;p&gt;Before everything, this first tip is meant for those that are still learning or want to learn C++. &lt;a href="https://www.learncpp.com/" rel="noopener noreferrer"&gt;Learn Cpp&lt;/a&gt; is a free website devoted to teaching you how to program in C++. Whether you’ve had any prior programming experience or not, the tutorials on this site will walk you through all the steps to write, compile, and debug your C++ programs, all with plenty of examples.&lt;/p&gt;

&lt;p&gt;When someones come to me questioning what they could do to become C++ developers, Learn Cpp is my first suggestion. It approaches from the very basic syntax and constructions, passing through data types and inheritance, up to more complex topics and even updates on newer versions of C++.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://www.learncpp.com/" rel="noopener noreferrer"&gt;learncpp.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  C++ shell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://cpp.sh/" rel="noopener noreferrer"&gt;C++ shell&lt;/a&gt; as the name suggests is an online C++ compiler shell. It's much simpler than the items that are to come in this list, but it gets the job done. If you want to quickly check something and see the output, it will be enough for you. It does support C++ 98, 11, and 14 and some warnings and optimization levels, but that's it.&lt;/p&gt;

&lt;p&gt;This is usually my go-to whenever I want to test some small code to see if it's behaving as I wanted and I'm not interested in anything fancier.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="http://cpp.sh/" rel="noopener noreferrer"&gt;cpp.sh/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Online GDB
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.onlinegdb.com/" rel="noopener noreferrer"&gt;Online GDB&lt;/a&gt; is like the improved version of the C++ shell. It's also an online compiler, but it also has a built-in feature for debugging using GDB. You can compile, run and debug code, not only it supports C++ (including C++ 11 to 17), it also works with languages such as Python, Rust, and many others.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://www.onlinegdb.com/" rel="noopener noreferrer"&gt;onlinegdb.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick C++ Benchmark
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://quick-bench.com/" rel="noopener noreferrer"&gt;Quick Bench&lt;/a&gt; is an online benchmarking tool intended to quickly and simply compare the performance of two or more code snippets. It does support different compilers (with many versions available), C++ from 11 to 20 (really!), different optimization levels, and other customizations.&lt;/p&gt;

&lt;p&gt;Not only it's super easy to set up the benchmark, but it will also create a chart with the comparison of the snippets. And if you are into it, you can still check the assembly, and see what are the instructions that are making your code slower.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fquickbench.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fquickbench.png" title="Quick bench chart" alt="Quick bench chart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://quick-bench.com/" rel="noopener noreferrer"&gt;quick-bench.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Perf Bench
&lt;/h2&gt;

&lt;p&gt;If Quick Bench didn't sound right to you, maybe Perf Bench will make it. Similar to the previous item, &lt;a href="https://perfbench.com/" rel="noopener noreferrer"&gt;Perf Bench&lt;/a&gt; it's an online C++ code profiler. It lets you write and benchmark C++ online and see latencies on charts, comparing performance between different versions of the code.&lt;/p&gt;

&lt;p&gt;What I really like about this tool is that it allows to nest different scopes of profilers and specify the number of loops for each profiler. Honestly, most of the time this is a bit overkill to my use, but on specific occasions, it's exactly what I need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fperfbench.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fperfbench.png" alt="Perf Bench"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://perfbench.com/" rel="noopener noreferrer"&gt;perfbench.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compiler Explorer (Godbolt)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://godbolt.org/" rel="noopener noreferrer"&gt;Compiler Explorer&lt;/a&gt; is an interactive compiler explorer website. With a huge list of compilers and languages supported, you can see what's the assembly of the code you are writing in real-time. Different tools and visualizations are available and the UI is very customizable.&lt;/p&gt;

&lt;p&gt;Although the focus of Compiler Explorer was (and I think it still is) to convert code into the assembly, it also has the support for execution. In this talk on &lt;a href="https://www.youtube.com/watch?v=kIoZDUd5DKw" rel="noopener noreferrer"&gt;CppCon 2019 from Matt Godbolt&lt;/a&gt;, creator of the Compiler Explorer, he presents the history of Compiler Explorer, some of the newer features (at that time), and some of the behind the scenes.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://godbolt.org/" rel="noopener noreferrer"&gt;godbolt.org/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cpp Insights
&lt;/h2&gt;

&lt;p&gt;Cpp Insights is a clang-based tool that does a source-to-source transformation. Its goal is to make things visible which normally, and intentionally, happen behind the scenes. As they say: It's about the magic the compiler does for us to make things work.&lt;/p&gt;

&lt;p&gt;You'll be able to see what the compiler actually sees, removing a lot of the syntax sugar we are used to. You can check out the &lt;a href="https://www.youtube.com/watch?v=Bt7KzFxcbgc" rel="noopener noreferrer"&gt;talk from Andreas Fertig on NDC Oslo 2017&lt;/a&gt; where he talks about these hidden costs of the language's features, and Cpp Insights is all about that!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fcppinsights.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthamara.dev%2Fassets%2Fimg%2Fposts%2Fcppinsights.png" alt="Cpp insights"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://cppinsights.io/" rel="noopener noreferrer"&gt;cppinsights.io/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;All the tools I talk about here are available online and have some way of sharing the code snippets with others and some are even integrated, which allows you to bring a code from one to the other with the click of a button.&lt;/p&gt;

&lt;p&gt;This by no means will replace having a compiler installed with other libraries you are using, but still, they are great tools for quick tasks, where you want to validate a solution, compare versions of the same code, or just are interested in learning more in-depth information on the compilation/language details.&lt;/p&gt;

&lt;p&gt;As an open-source advocate, I also want to highlight that many of these tools are open source. You can check the repositories from their sites and collaboration is welcome.&lt;/p&gt;

&lt;p&gt;Hope this is useful, and please share what are the online (or maybe local) tools you use that help you in the development process.&lt;/p&gt;

&lt;p&gt;As always, I'm on Twitter &lt;a href="https://twitter.com/thamyk" rel="noopener noreferrer"&gt;@thamyk&lt;/a&gt;, just waiting to hear what you think!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Code Review - What is and why you should care</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 26 Jul 2021 14:37:18 +0000</pubDate>
      <link>https://dev.to/thamara/code-review-what-is-and-why-you-should-care-480a</link>
      <guid>https://dev.to/thamara/code-review-what-is-and-why-you-should-care-480a</guid>
      <description>&lt;p&gt;Recently, I gave a talk on Code Review at the WomentTech Global Conference (I even talk about how it all happened in this &lt;a href="https://thamara.dev/posts/my-learning-while-becoming-a-conference-speaker/"&gt;post&lt;/a&gt;). It was such a great experience, I decided to share in a text (and some GIFs). It ended up becoming quite a long post, so my suggestion is to pair the reading with a &lt;a href="https://www.thekitchn.com/how-to-make-a-chai-tea-latte-242520"&gt;Chai Latte&lt;/a&gt; (or really anything you like to drink).&lt;/p&gt;

&lt;p&gt;As always, feel free to talk with me about this, or really anything, on Twitter, &lt;a href="https://twitter.com/thamyk"&gt;@thamyk&lt;/a&gt;. Other contacts on my &lt;a href="https://thamara.dev/about/"&gt;about&lt;/a&gt; page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Story time
&lt;/h2&gt;

&lt;p&gt;Before we jump into code review, let me share two stories with you.&lt;/p&gt;

&lt;p&gt;In 1962, NASA launched the &lt;a href="https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=MARIN1"&gt;Mariner 1&lt;/a&gt;, a vehicle intended to perform a Venus flyby. Roughly 5 min after launch, the Range Safety Offices called for self-destruction of the rocket. This caused a loss of more than 327 million dollars.&lt;/p&gt;

&lt;p&gt;Some years later, in 1999, NASA developed a satellite that was supposed to orbiter Mars, collecting weather information from the planet, the &lt;a href="https://llis.nasa.gov/llis_lib/pdf/1009464main1_0641-mr.pdf"&gt;Mars Climate Orbiter (MCO)&lt;/a&gt;. But the satellite never really got into Mars' orbiter, becoming lost in space (literally). This caused a loss of 125 million dollars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/YJjvTqoRFgZaM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/YJjvTqoRFgZaM/giphy.gif" alt="burning-money"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do both of these stories have in common? Well, both have their root cause boiled down to issues in software. Issues that are commonly caught during code review. The Mariner 1 counted with the omission of a hyphen in coded computer instructions, which allowed transmission of incorrect guidance signals to the spacecraft. While the MCO had two important components communicating with each other, one considering the imperial measuring system and the second the metric one. Needless to say, recipe for disaster.&lt;/p&gt;

&lt;p&gt;One important disclaimer here is that I'm in no way blaming developers from NASA, nor stating they don't do code review. What I want you to take from these stories is that: software errors can get pretty costly, especially when the software is in production. And I'm not alone claiming this.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://ftpmirror.your.org/pub/misc/ftp.software.ibm.com/software/au/rational/downloads/RAW14109USEN.pdf"&gt;study done by IBM&lt;/a&gt; estimated that the cost of an error catch after the release of the product is 30 times the cost if caught during specification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ITb02Nl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/costoferrors.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ITb02Nl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/costoferrors.png" alt="Cost of erros during the software development process. Specification: 1X, Implementation: 5X, Tests: 10-15X, After release: 30X"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code Review will be able to contribute to catching errors during implementation, which helps lower the cost of the development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is code review?
&lt;/h2&gt;

&lt;p&gt;We went a little ahead, so let's back down and answer an important question. What is this code review I've been talking about?&lt;/p&gt;

&lt;p&gt;Code Review is an activity where one or more people go over someone else's code, proving feedbacks (negatives and positives). During this activity, the following are identified:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Completeness: Is the problem being resolved as a whole? Any missing (and important) part?&lt;/li&gt;
&lt;li&gt;Consistency: Is it following the guidelines for the product? And the guidelines for the code?&lt;/li&gt;
&lt;li&gt;Side effects: Could this cause unwanted effects?&lt;/li&gt;
&lt;li&gt;Maintainability: Will this be easy to maintain? Coming back at this code one year from now, will we be able to understand it and the reasoning behind it?&lt;/li&gt;
&lt;li&gt;Tests: Are there enough tests for this? Are the tests covering everything?&lt;/li&gt;
&lt;li&gt;Performance: Could this cause performance issues? Is it optimal?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Types of review
&lt;/h2&gt;

&lt;p&gt;There are many ways of code review. Here I talked about 3 types I find more common in the routine of the corporations and projects out there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pair programming
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Pair_programming"&gt;Pair programming&lt;/a&gt; is a well-known practice in our field. In it, two programmers work on developing something together, using only one workstation. During the development, possible problems are spotted and fixed.&lt;/p&gt;

&lt;p&gt;Using this allows for fast response between peers, reducing overhead between finding an issue and fixing it. It's great for solving complex problems, especially when each part knows only half of the domain, or even when both parts don't know much about the problem, and together learn and work on the solution.&lt;/p&gt;

&lt;p&gt;The downside of such a practice and one of the reasons why it cannot be used as a silver bullet is that it required the full dedication and allocation of two people.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live review
&lt;/h3&gt;

&lt;p&gt;Live review, as the same suggests, is when you call for one or more people and presenting the code on a screen, go over it, reviewing together.&lt;/p&gt;

&lt;p&gt;Again, the upside is for this type of review is that the turnaround time between peers is reduced. The person who is reviewing can get answers from who developed as they go through the code together. Because of this, it's a great option when the reviewer needs further clarification on the context.&lt;/p&gt;

&lt;p&gt;One big issue with this is that it ends up forcing a context switch for reviewers, adding one more (among the many) meetings in their day. The person has to stop doing something at the given time, go to the review session, and later come back to that something that was stopped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous review
&lt;/h3&gt;

&lt;p&gt;Maybe the most common one, the asynchronous review happens, well, asynchronously. The person sends a review request to the reviewers, and they will go over that, sending the comments back whenever they have a chance to look at it. The requester will receive such comments, work on the code, send it back, and after some iterations, the code is approved.&lt;/p&gt;

&lt;p&gt;Many tools are available that auxiliaries this process. &lt;a href="https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request"&gt;GitHub's pull request&lt;/a&gt; system is one of the most commons, but others are out there.&lt;/p&gt;

&lt;p&gt;This breaks some dependencies on the flow, creating specific steps in the whole software development flow, as well as helps to reduce the context switch for the reviewers: they can tackle reviews at their time. But of course, this comes with the penalty of possibly taking more time between the first request and final approval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which one should I choose?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/WyeodYfrqvHCo/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/WyeodYfrqvHCo/giphy.gif" alt="everything is ok"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of them!&lt;/p&gt;

&lt;p&gt;Each one will fit a different kind of problem, and using one should not prevent the use of another in the same situation. For example, you might have created something using pair programming but still, ask for a review from others. Or do the first session of live review and then submit the changes to a review platform.&lt;/p&gt;

&lt;p&gt;The important thing here is to know that these options exist and use them as you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I include Code Review in my process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Increase software's quality
&lt;/h3&gt;

&lt;p&gt;If you refer to what is identified during code review, you'll notice that the general focus of this process is to increase the quality of the code. Reduce bugs and also preventing the code from becoming a huge problem in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Increase customer's satisfaction
&lt;/h3&gt;

&lt;p&gt;No customer likes buggy software, so if the quality of the product increases, you'll most likely see the satisfaction of the customers raising too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/VhWVAa7rUtT3xKX6Cd/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/VhWVAa7rUtT3xKX6Cd/giphy.gif" alt="quality"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduce cost
&lt;/h3&gt;

&lt;p&gt;Going back to the story time, bugs are costly, and catching them as early as possible will reduce the cost of the product developed. This might take some time to be noticeable or even go unnoticed, but believe, it's there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduce bus factor
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Bus_factor"&gt;bus factor&lt;/a&gt; is one of the terms I like the most. It is a measurement of the risk resulting from information and capabilities not being shared among team members, derived from the phrase “in case they get hit by a bus”. What would happen to your product if that one person who owns solely an important component gets hit by a bus? Would your product survive? How long would it take to get someone to take ownership of that?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/UqffnNae48Gxq/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/UqffnNae48Gxq/giphy.gif" alt="hit by a bus"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, we don't want anyone getting hit by buses. But many reasons could make someone who is an important key in a project leave it. Maybe the person left the company, maybe it got send to another team, maybe it had to take a leave. It doesn't really matter the reason, the point is your team is left with a big problem in their hands.&lt;/p&gt;

&lt;p&gt;By implementing code reviews, even if you have someone to own by themselves something because others are also looking at the code, reviewing it, they start to get a feeling of that too. And, if a bus hit (again, metaphorically), you'll have other people who would be more prepared to step up and assume that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mentor of juniors
&lt;/h3&gt;

&lt;p&gt;You might've heard of “we learn things better by doing”, which for the dev world could not be more true. Code review is a step-up on that. Not only someone is doing, but it's receiving feedback from people that know more about the software or the language, helping this person ramp up.&lt;/p&gt;

&lt;p&gt;Obviously for this to work you need to count on the collaboration of the more seniors of your team, to not only correct someone but to actually explain and teach on why something should be done in a given way. In my experience, this is not a burden on the review, but instead, is an investment in the future (which pays off really nicely) and an extension of other learning initiatives your team has.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guarantee project's guidelines
&lt;/h3&gt;

&lt;p&gt;Directly from &lt;a href="https://en.wikipedia.org/wiki/Coding_conventions"&gt;Wikipedia&lt;/a&gt;, coding guidelines or coding conventions are a set of guidelines for a specific programming language that recommend programming style, practices, and methods for each aspect of a program written in that language. These conventions usually cover file organization, indentation, comments, declarations, statements, white space, naming conventions, programming practices, programming principles, programming rules of thumb, architectural best practices, etc.&lt;/p&gt;

&lt;p&gt;These guidelines are essential for improving the maintainability of your software, and guess what process can ensure these are kept across all your codebase? Yes! Code review.&lt;/p&gt;

&lt;p&gt;Many of these guidelines can be automated by tools and scripts, but still, human inspection is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Increase collaboration
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/dSetNZo2AJfptAk9hp/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/dSetNZo2AJfptAk9hp/giphy.gif" alt="team work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last but not least, code review allows for increased collaboration in your team. Even if you have a developer working alone in a given task/component, because they are sending their work to review, others get to be a part of the solution too. This creates a sense of teamwork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips for applying Code Review
&lt;/h2&gt;

&lt;p&gt;What to start applying this or even enhancing the process you have today?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/8VIRj0jsCPIIBpKSDK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/8VIRj0jsCPIIBpKSDK/giphy.gif" alt="I dont know where to start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fear not! I have some tips to help you!&lt;/p&gt;

&lt;h3&gt;
  
  
  Review everything
&lt;/h3&gt;

&lt;p&gt;First and foremost: review everything. Just one line change? Review it. You never know when a possible typo or missing hyphen could cause problems.&lt;/p&gt;

&lt;p&gt;Believe me when I say this: sometimes the smallest change can cause a ripple effect you cannot foresee. But if code review is stated, it can reduce the chances of some disastrous changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make lists
&lt;/h3&gt;

&lt;p&gt;If you are starting with reviews, make lists of what you'll be checking. This can help you get comfortable with the flow and after a while you won't need these lists anymore.&lt;/p&gt;

&lt;p&gt;Here's an example of a list you can get inspired by (&lt;a href="https://www.evoketechnologies.com/blog/code-review-checklist-perform-effective-code-reviews/"&gt;source&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Code formatting&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Coding best practices&lt;/li&gt;
&lt;li&gt;Non-functional requirements: maintainability, reusability, reliability, extensibility, security, performance, scalability, usability&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Automate what's possible
&lt;/h3&gt;

&lt;p&gt;How I love automating things. And for code review, this can be your best friend. From the list I mention in the item before, you might be able to spot lots of checks that automated tools can do (instead of the human). Use them to your advantage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/12qq4Em3MVuwJW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/12qq4Em3MVuwJW/giphy.gif" alt="automation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It might take a few manual iterations at first (as any task you want to automate) to get a grip on what and how something should be done. But once you have this, automate whatever is possible and safe and leave the more complex steps to human reviewers.&lt;/p&gt;

&lt;p&gt;The idea is not to substitute humans but to use machines to make our life easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plan and share the load
&lt;/h3&gt;

&lt;p&gt;Code review takes time and it should be included in your process and planned accordingly. When planning your and your team's work, take into consideration the time spent on reviews. Not only on doing, but asking for reviews and iterating to fix the possible problems.&lt;/p&gt;

&lt;p&gt;Also, share the load of reviews among every one of your team. The idea is not to make someone's job to only do reviews. It should be a task included in the jobs description of each one, regardless of level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everybody gets in the game
&lt;/h3&gt;

&lt;p&gt;As I mention, everybody should be included and use the review process. It's not just seniors reviewing code from juniors. Sometimes we need the fresh eyes of someone who is less experienced to spot issues in the code. Use that to your advantage and make a rule for everybody getting into this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review before merge
&lt;/h3&gt;

&lt;p&gt;I'm not going to lie: I already convinced myself on a few occasions that I would push/merge some code and do the review afterward, aka, after it was already in production. Such times were commonly motivated by some deadline or critical of the issue and it made sense at the time. But this is a terrible idea! And trust me, I regretted it.&lt;/p&gt;

&lt;p&gt;If you have code in production and you need to do some adjustments, things get hard, and possibly you already lost the momentum on that task you were doing and it becomes a big source of a context switch.&lt;/p&gt;

&lt;p&gt;So the tip here is to make such occasions as exceptions as possible. Make sure your process has a strict rule of no push/merge without review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time management
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/lffW0sDfrzBXr1AxME/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/lffW0sDfrzBXr1AxME/giphy.gif" alt="time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I already mentioned that code reviews take time. You might be looking into 1-2 hours a day for reviews if your team is big, even more depending on your position and the work you do. Deciding to take those all at once can be problematic.&lt;/p&gt;

&lt;p&gt;Several researchers out there tried to measure the attention span of adults, but they have a hard time converging. But you know yourself: how much time can you take a task with all the attention required, not getting distracted by your phone, emails, messages on Slack, or whatever? Whatever your answer was, this should be a limit on the time you take reviews at once.&lt;/p&gt;

&lt;p&gt;For me, this time is about 40-45min. So if I have ~2 hours of review to do, I'll break it into chunks. Do some in the morning, as I start my day. After lunch do some more. And finally close to the end of the day. Using this tactic, I can guarantee that when reviewing, my attention is focused on that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace the subconscious implications
&lt;/h3&gt;

&lt;p&gt;If you are starting to apply code review, if you are a junior, or even if you are just a regular person who puts a lot of pressure on yourself, there's a big chance the idea of showing your code to the world, or actually to a few specific people, might frighten you. You are not alone!&lt;/p&gt;

&lt;p&gt;I can say that until this day, after more than 8 years of experience as a software engineer, depending on the work I do or who is going to review it, I get kind of scared. Scared that people will criticize me through my work, or judge me on whatever scale they have. But I can safely say that this fear is totally a thing in my head, and I make sure to never hold me back from doing my job or ask for code reviews.&lt;/p&gt;

&lt;p&gt;What I do instead, and leave as a tip for you, is to embrace this fear. Let it motivate you to create the very best piece of software you can. If you get some issues being raised during review, learn from them and improve yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't take it personally
&lt;/h3&gt;

&lt;p&gt;Really connect to the last item, never take a review comment personally. You will receive critics, but they are not towards you. They are issues on a piece of code you wrote, and you can (and hopefully will) learn from those.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I hope I could shed some new light for you on code review. I only scratched the surface, and there's a lot more information on the web if you want to get deeper into it.&lt;/p&gt;

&lt;p&gt;I really love and support code reviews. I see it as an essential part that has helped shape the developer I'm today, and even after years of experience, I keep learning new things whenever I ask for a review.&lt;/p&gt;

&lt;p&gt;If you want to discuss something about what I talk about here, tell me your experiences with it, I'm more than happy to chat with you. As always, you can find me on Twitter at &lt;a href="https://twitter.com/thamyk"&gt;@thamy&lt;/a&gt;, you can send me an email at &lt;a href="mailto:tkcandrade@gmail.com"&gt;tkcandrade@gmail.com&lt;/a&gt;, or even come by at my &lt;a href="https://www.linkedin.com/in/thamara-andrade/"&gt;LinkedIn&lt;/a&gt; profile.&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Code Annotation: a VSCode extension for adding notes on your code without commiting</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 19 Jul 2021 15:07:53 +0000</pubDate>
      <link>https://dev.to/thamara/code-annotation-a-vscode-extension-for-adding-notes-on-your-code-without-commiting-2e13</link>
      <guid>https://dev.to/thamara/code-annotation-a-vscode-extension-for-adding-notes-on-your-code-without-commiting-2e13</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr;
&lt;/h2&gt;

&lt;p&gt;Code annotation is a Visual Studio Code extension that creates and tracks annotations from your source code without actually committing comments on your code.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://marketplace.visualstudio.com/items?itemName=tkcandrade.code-annotation"&gt;download Code Annotation&lt;/a&gt; directly from the Marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;When I'm investigating some bug, or just going through the code for some reason, it's very common that I came to some realizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oh oh, this code is too strange, this shouldn't be like this, need to check it later&lt;/li&gt;
&lt;li&gt;Damm, this is a horrible name for this method/variable&lt;/li&gt;
&lt;li&gt;I need to come back to this function after when popping the calling stack I'm traversing&lt;/li&gt;
&lt;li&gt;I need to fix the use of this API here, here, and here (in multiple files)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But because this happens while I'm working on something else, I don't want to stop, take care of it, and get back. So, what I used to do was either to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open my to-do list app, insert an entry on it for the future, and possibly not adding enough context for the future making it a useless entry&lt;/li&gt;
&lt;li&gt;Add a not-so-beautiful comment like &lt;code&gt;// DO NOT COMMIT: Thamara check this&lt;/code&gt;, which usually lead to me forgetting and committing it anyway (and having to remove, rebase, merge, whatever)&lt;/li&gt;
&lt;li&gt;Use of the adding breakpoints feature on VSCode, and frequently losing track of why I tagged something, as well as getting my actual breakpoints all mess up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Needless to say, I needed a better system.&lt;/p&gt;

&lt;p&gt;To summarize the problem: I wanted to add some notes that would be tied to a code, but I could include a better description of why I was adding that note. I wanted to track what I added and I didn't want to commit anything (read: didn't want to rely on adding TODOs to the code).&lt;/p&gt;

&lt;p&gt;I went over several extensions on the VSCode marketplace and could not find anything. So I did the very best thing I do when I have a problem: I solved it myself. If there was no available solution, I would build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Annotation
&lt;/h2&gt;

&lt;p&gt;Code annotation is a Visual Studio Code extension that creates and tracks annotations from your source code without actually committing comments on your code.&lt;/p&gt;

&lt;p&gt;It has a nice panel that shows your notes and their details, including status: completed or not. You can remove/edit/add new notes using shortcuts or right-clicking on some selected code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fuZlOfkn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/code-annotation-demo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fuZlOfkn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/code-annotation-demo.png" alt="Screenshot of the extension UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://marketplace.visualstudio.com/items?itemName=tkcandrade.code-annotation"&gt;download Code Annotation&lt;/a&gt; directly from the Marketplace.&lt;/p&gt;

&lt;p&gt;As an open-source extension, it's &lt;a href="https://github.com/thamara/vscode-code-annotation"&gt;available in GitHub&lt;/a&gt; and you are more than welcome to contribute to it by reporting issues, suggesting improvements or developing new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned: Perfection is indeed the enemy of done
&lt;/h2&gt;

&lt;p&gt;I have started working on this in August 2020, commit the base for the extension, and stopped. Around Hacktoberfest some people stopped by the repository and contributed too (how I love the open-source community!). By November of that year, it was pretty much what it looked on this first public release.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lD4EM-HT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/code-annotation-commit-history.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lD4EM-HT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thamara.dev/assets/img/posts/code-annotation-commit-history.png" alt="Commit history in the extension's repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since November, I've been using it, but put off publishing it for "a bit". What took less than 2 months to be done (August and October), took 8 months for me to publish it. YES! EIGHT MONTHS.&lt;/p&gt;

&lt;p&gt;I initially put the blame on it working so well and solving my problem that I forgot about it, but the truth is that I wanted the first version to be a super complete extension. I have so many ideas, but this would require the time I didn't want to commit to.&lt;/p&gt;

&lt;p&gt;That was when I bumped into this article on "&lt;a href="https://www.forbes.com/sites/deeppatel/2017/06/16/why-perfection-is-the-enemy-of-done/?sh=6db2b7f84395"&gt;Why Perfection is The Enemy of Done&lt;/a&gt;", and let me tell you, the shoe fitted.&lt;/p&gt;

&lt;p&gt;So, I decided to publish anyway. Did a few minor adjustments and released it to the world.&lt;/p&gt;

&lt;p&gt;After a few days, I presented it to some coworkers and they loved it! They had the same problems as I (some didn't even realize that until I pointed out), and they were more than happy to start using it.&lt;/p&gt;

&lt;p&gt;So, lesson learned: Done is better than perfect.&lt;/p&gt;

&lt;p&gt;As always, you can find me on Twitter at &lt;a href="https://twitter.com/thamyk"&gt;@thamy&lt;/a&gt;, &lt;a href="//mailto:tkcandrade@gmail.com"&gt;tkcandrade@gmail.com&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/thamara-andrade/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>extension</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>My learnings while becoming a conference speaker</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 12 Jul 2021 14:28:41 +0000</pubDate>
      <link>https://dev.to/thamara/my-learnings-while-becoming-a-conference-speaker-59oj</link>
      <guid>https://dev.to/thamara/my-learnings-while-becoming-a-conference-speaker-59oj</guid>
      <description>&lt;h2&gt;
  
  
  Before everything
&lt;/h2&gt;

&lt;p&gt;In 2020, before the pandemic hit us, I had included in my life goals to attend a tech conference. With COVID and most of the conferences being canceled or postponed, I thought this goal would set sail (among many of other of my goals). But then everybody got used to the idea of virtual conferences and I had the opportunity to attend CppCon. I talked about this experience in &lt;a href="https://thamara.dev/posts/cppcon-2020-the-halway-track/"&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At CppCon I got to know many of the speakers that I only knew before through YouTube, blogs, and Twitter, and to my surprise, they were like, real people. I know this sounds dumb, but believe me, it was how I felt. This was really important to me because it demystified the whole speaker role, and the path to becoming one started sounding so much accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  I had a dream, and then, another dream, and then it was reality
&lt;/h2&gt;

&lt;p&gt;By then, I had another life goal: speak at a conference. And again, what I thought would take some time, happened in November of 2020, when I gave a talk on &lt;a href="https://www.shestech.org/2020"&gt;She'sTech conference&lt;/a&gt;, the largest event of women in tech from Brazil. I was overwhelmed by happiness, and again, I raised my goal to talk at an international conference. And well, it happened.&lt;/p&gt;

&lt;p&gt;It started with an email from the Women in Tech group at the company I work for. It was a list of next conferences with the call to papers open. One of those was WomenTech Global Conference (WTGC). As I had already prepared a talk on Code Review for the She'sTech conference, I decided to go with this topic, as I was already comfortable with the topic.&lt;/p&gt;

&lt;p&gt;I applied on a Sunday night, and, before even having time to speak and notify my manager of my intentions, on Monday morning I received the email stating that my talk was approved. The company I work for encourages joining such opportunities, so it wasn't a problem to have the talk approved before having time to talk with management. It was all sorted out, and I gave the presentation in June 2021.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/2vqCeZa9FDGGe8moT9/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/2vqCeZa9FDGGe8moT9/giphy.gif" alt="pull-it-off"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned in this process
&lt;/h2&gt;

&lt;p&gt;So, what I learned from these experiences? First and foremost, I learned that I really love giving presentations on topics I'm passionate about. This was already something I was pretty used to in more intimate environments, but talking to an audience that I didn't know was still pretty frightening. This didn't hold me back and has only made me stronger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't sell yourself short, you have something to share
&lt;/h3&gt;

&lt;p&gt;Choosing a topic to talk about was possibly my main struggle. What could I share with the world? I had to work on changing my mindset and stop thinking that what I had to say was already public domain. This took some practice, but most of all, it took a lot of work on stopping underselling me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Ddkp2ltJLqmS20UQKX/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Ddkp2ltJLqmS20UQKX/giphy.gif" alt="its-mindset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this mental switch was flipped, and I must add that it was not overnight, I could start thinking about topics I felt ready and comfortable to present to others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be ready to receive NOs
&lt;/h3&gt;

&lt;p&gt;This whole post is about the YES, but believe, there are NOs too. On my first no, I felt horrible, and after a few time to process it, I learned that sometimes it's just a matter of your presentation not fitting in the conference. Other times you just got unlucky. I kept trying, adjusting and didn't let it take me down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your presentation doesn't need to exist for you to submit the call for papers
&lt;/h3&gt;

&lt;p&gt;Most call for papers doesn't require the full presentation to be ready. Instead, they ask for the outline, takeaways, and target audience. This should be simple to get ready if you have already the idea in mind. Understanding this prevented my perfectionist side from stopping me. &lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaways
&lt;/h3&gt;

&lt;p&gt;Ok, if I didn't need the full presentation ready, how can I define the outline? The answer: think about the key takeaways. This should be what you want the audience to leave out of your session, and work on the presentation should deliver this. Writing those down helped me shape and define the outline, and later, guided my work on the actual presentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Words are hard
&lt;/h3&gt;

&lt;p&gt;Names are the worst. But naming is very important. This is probably what will catch the attention of the audience before even reading the outline for the talk.  When brainstorming names, I focused on names that would be catchy and instigate the interest of others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask for feedback
&lt;/h3&gt;

&lt;p&gt;Especially if you are a first-timer speaker, ask for feedback from friends and coworkers. This is valid even before submitting the call for paper. Discuss what are your intentions, what kind of information you want to pass, and how you think of doing this. &lt;/p&gt;

&lt;p&gt;If your talk was approved, schedule some time with those close to you and present it to them. This will help you not only with the content, identifying what you need to explain better for example, but also work as a dry run to get the feeling of the time and possible questions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LROiqvSaCUzyOjT2yg/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LROiqvSaCUzyOjT2yg/giphy.gif" alt="we-are-on-it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A friend of mine does this thing where he presets and asks for feedback from his wife, someone who isn't in the same field as him. If she understands, the presentation is great. This might not be true for every domain, but sure is something to try out.&lt;/p&gt;

&lt;p&gt;I have done all of those, from presenting to my parents to presenting to friends who are highly skilled at the topics I choose, and I could not be happier with the feedback. It allowed me to change some details and make the presentations better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;A talk is always about telling a story, and we do this every day: we tell stories about our life, what we have done, what we will be doing, everything. Conference speakers are out there telling stories just like we do in our daily life, the difference is that they already overcome the fear of public speaking (some might still even have it) and had worked on learning how to tell the stories to others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/IoQETeY2ue5bi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/IoQETeY2ue5bi/giphy.gif" alt="Stories"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to get in touch, you can contact me on Twitter (&lt;a href="https://twitter.com/thamyk"&gt;@thamyk&lt;/a&gt;) or by email at &lt;a href="mailto:tkcandrade@gmail.com"&gt;tkcandrade@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>speaking</category>
      <category>learning</category>
      <category>confererence</category>
    </item>
    <item>
      <title>How to sleep... in different programming languages</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Tue, 16 Feb 2021 17:56:31 +0000</pubDate>
      <link>https://dev.to/thamara/how-to-sleep-in-different-programming-languages-100i</link>
      <guid>https://dev.to/thamara/how-to-sleep-in-different-programming-languages-100i</guid>
      <description>&lt;p&gt;Every now and then, as a developer, we need to add a sleep in our code. Usually to make some test work, or god knows the reason. In particular, I use this a lot in Tcl, as this is the primary language for the tests I write at work. And there was not a single time where I tried a simple "sleep" command, only to have it fail. The reason? In Tcl, the sleep command is actually "after", something I find exceptionally not natural.&lt;/p&gt;

&lt;p&gt;To prove my point on the wrong name for such command in Tcl, I decided to investigate how the same is achieved in different languages. In all examples below, I'll be implementing a sleep of 3 seconds and judging the language on the way it allows the sleep to be implemented. The languages I choose are based on the most popular programming languages, which I found on some random site, and I cannot guarantee the veracity.&lt;/p&gt;

&lt;p&gt;Please note that I'm not proficient in many of the languages I mention here. Feel free to contact me on &lt;a href="https://twitter.com/thamyk"&gt;@thamyk&lt;/a&gt; if you found some error, want to give feedback, or think I should change my grades.&lt;/p&gt;

&lt;h2&gt;
  
  
  C
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sleep(3); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8/10&lt;/strong&gt;, does not allow precise units unless you want to use &lt;code&gt;usleep&lt;/code&gt;, but still is limited to microseconds or seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  C++11
&lt;/h2&gt;

&lt;p&gt;Using chrono and thread libraries, is as beautiful as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;this_thread&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sleep_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;10/10&lt;/strong&gt;, beautiful and expressive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go
&lt;/h2&gt;

&lt;p&gt;Using time package, it's pretty simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;10/10&lt;/strong&gt;, direct and offers a simple way to convert between the units.&lt;/p&gt;

&lt;h2&gt;
  
  
  Java
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8/10&lt;/strong&gt;, simple but only accepts milliseconds as the parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript
&lt;/h2&gt;

&lt;p&gt;As far as my research and knowledge go, there's not a way of stoping the execution of Javascript. Still, there's something similar that can be achieved using a callback, like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
           &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5/10&lt;/strong&gt;, at least allow something similar to be done, but not in a good way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;

&lt;p&gt;Using time module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8/10&lt;/strong&gt;, very practical, but requires the argument in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruby
&lt;/h2&gt;

&lt;p&gt;From my &lt;a href="https://stackoverflow.com/questions/1329967/tell-ruby-program-to-wait-some-amount-of-time"&gt;investigation&lt;/a&gt;, you can simply use a sleep function or use the ActiveSupport library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;10/10&lt;/strong&gt;, maybe the grade should be lower if using ActiveSupport is not something ordinary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust
&lt;/h2&gt;

&lt;p&gt;For being syntactically similar to C++, the sleep function is also similar to C++, using thread and time libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;10/10&lt;/strong&gt;, allow easy conversion between units.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scala
&lt;/h2&gt;

&lt;p&gt;As a close friend of Java, Scala's sleep is pretty much the same as Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nv"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8/10&lt;/strong&gt;, simple, direct, but requires milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Swift
&lt;/h2&gt;

&lt;p&gt;As I have absolutely no proficiency in Swift, I'll be sharing two options for this. The first one is based on Unix's sleep command, and the second one is closer to the implementation of a callback. (Based on &lt;a href="https://stackoverflow.com/questions/27517632/how-to-create-a-delay-in-swift"&gt;this stack overflow question&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Option 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option 2, considering Swift &amp;gt;= 3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;
&lt;span class="kt"&gt;DispatchQueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asyncAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;deadline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Put your code which should be executed with a delay here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6/10&lt;/strong&gt;, does allow sleep in multiple ways but rely on Unix syntax or require you to use a Dispatch Queue and some other logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tcl
&lt;/h2&gt;

&lt;p&gt;Argh!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tcl"&gt;&lt;code&gt;after 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1/10&lt;/strong&gt;, terrible name, but at least allows the sleep, and just for this will get one point.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;First of all, I must say that using a sleep in your code is not the best solution in most cases. Still, as I mentioned before, there are indeed scenarios where you do want that. Based on this, I was astonished at how easy it's in most languages to do what is desired.&lt;/p&gt;

&lt;p&gt;The drawback of many languages is the necessity to remember precisely the type of unit you need to use on the call (gravitating between seconds and milliseconds).&lt;/p&gt;

&lt;p&gt;Some languages seem to overcome such limitation through external libraries, which I think is a great solution and would be great if somehow this could be incorporated in newer releases of the language.&lt;/p&gt;

&lt;p&gt;That all being said, I conclude this post with the confirmation: Tcl has the worst command for sleep!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Finally got an answer to a long-lasting question - How many times I watched a show on Netflix</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Mon, 16 Nov 2020 00:20:05 +0000</pubDate>
      <link>https://dev.to/thamara/finally-got-an-answer-to-a-long-lasting-question-how-many-times-i-watched-a-show-on-netflix-1i6e</link>
      <guid>https://dev.to/thamara/finally-got-an-answer-to-a-long-lasting-question-how-many-times-i-watched-a-show-on-netflix-1i6e</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QMLZ4LGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thamara/thamara.dev/master/_posts/images/netflix-time.png%3Ftoken%3DAAGOR373HURRTD337E4UK427XL7K4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QMLZ4LGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thamara/thamara.dev/master/_posts/images/netflix-time.png%3Ftoken%3DAAGOR373HURRTD337E4UK427XL7K4" alt="Netflix data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I subscribe to Netflix for almost 10 years now. Of course, I have my favorite series and movies that I repeatedly watch, especially before bedtime. With this, I came to memorize many scenes, especially from Friends, Brooklyn 99, and Modern Family. I always wondered how many times I watched a show, but Netflix never gave me that answer. Until now.&lt;/p&gt;

&lt;p&gt;A few days ago, I found out it was possible to download all my data from &lt;a href="https://www.netflix.com/account/getmyinfo"&gt;Netlix&lt;/a&gt;, which included my viewing history. As the name suggests, the viewing history has the logs for all the things you watch on Netflix, with time, duration of the session, content title, and more. So, it was just a matter of manipulating the data little, and I would finally have the answer to a question I have for a while.&lt;/p&gt;

&lt;h2&gt;
  
  
  The straight (and boring) answer
&lt;/h2&gt;

&lt;p&gt;My first approach was pretty straightforward, using all my knowledge from Excel, creating some formulas to filter and sum the hours. A few minutes later I got my answer, and to my surprise, I found out I had watched Friends almost 20 times!&lt;/p&gt;

&lt;p&gt;I got my answer, but let's be sincere, how much fun is a little cell on Excel? There was so much I could still do and also make it beautiful. It was also an excellent opportunity to write some Python and play with &lt;a href="https://d3js.org/"&gt;D3&lt;/a&gt;, something I've wanted to do for a while. I often feel the need and the opportunity to use D3 but haven't gotten familiar with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr;
&lt;/h2&gt;

&lt;p&gt;If you don't want to read the details, you can go directly to this &lt;a href="https://thamara-my-netflix-data.netlify.app/"&gt;example page&lt;/a&gt;, to see the report format. Or to this &lt;a href="https://github.com/thamara/my-netflix-data"&gt;project GitHub page&lt;/a&gt; where you can fork/download and use on your own data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data
&lt;/h2&gt;

&lt;p&gt;I'm by no means a specialist in Data Analysis or Data Visualization. Still, I know that the first step in working on a data set is to understand it, and that's what I did. Alongside the information Netflix makes available from your account, there's also a Cover Sheet that contains all the documentation for all the data you'll receive. This made it very easy to understand all the fields in the viewing activity CSV file. Here is the crucial information from it w.r.t. this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile Name: the name of the profile in which viewing occurred
Duration: the length of the viewing session
Title: the TV show or movie viewed
Supplemental Video Type: Videos other than a TV show or a movie (such as trailers)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For my analysis, I wanted to ignore all the entries where "Supplemental Video Type" had a value: the different videos such as trailers, recapitulations, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Title adjusts and extraction
&lt;/h3&gt;

&lt;p&gt;From checking the data, I could see that I would be able to also break down the titles to recover in case of a TV show, what the show was, the season, and the episode. Here are a few examples of the titles of a few entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Brooklyn Nine-Nine: Season 6: The Honeypot (Episode 7)
The IT Crowd: Series 3: Tramps Like Us (Episode 3)
Chilling Adventures of Sabrina: Part 1: Chapter Eleven: A Midwinter's Tale (Episode 11)
Skins: Vol. 2: Tony and Maxxie (Episode 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, although there is not much consistency between the naming of the seasons, with one regular expression, I could capture the series title, the season, and also the episode name. This might fail for some languages/shows, but it worked pretty well in my data as a heuristic. I had to add some translations because my data had entries both in English and in Brazilian Portuguese. The regexp looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s"&gt;'(.*): (Season|Part|Vol\.|Series|Chapter|Temporada|Parte|Universo|Capítulo) ([ a-zA-Záéíê\d]*( Remix)*): (.*)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Duration
&lt;/h3&gt;

&lt;p&gt;To make my life easier, I decided to convert all the durations from the format "&lt;code&gt;HH:MM:SS&lt;/code&gt; ", to a single integer seconds. This allows me to sum all the durations without caring for the format. Later in the flow, I could just convert back from seconds to some more user-friendly value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 0:01:05 -&amp;gt; 65
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;durationTimeToSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;# 65 -&amp;gt; 00:01::05
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;secondsToDurantion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;remainingSeconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;remainingSeconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;remainingSeconds&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'{:02d}:{:02d}:{:02d}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remainingSeconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Processing the data
&lt;/h2&gt;

&lt;p&gt;I think now is a good time to say that my Python skills are not the best, and on top of that, I'm really rusty. There's possibly a lot of better ways of doing what I'm doing, so don't focus on how I'm solving the problem, and don't take that as the correct way. Anyway, let's continue.&lt;/p&gt;

&lt;p&gt;My script starts by processing the CSV information, filtering the data I don't want (in this case, only ignore trailers and the particular kinds of video), and creating an array with the specific information I want, as well as the profiles available in my account. From that, I break it down into two sets of data, movies, and series. Basically, what I do is sum up the balance for all the occurrences of the same entry in each profile.&lt;/p&gt;

&lt;p&gt;Well, at this point, I do a lot of for-loops and a lot of ifs, and in the end, I got data in the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# for movies
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'profile 1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'movie 1'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3974&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'movie 2'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3412&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'movie 3'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3974&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;'profile 2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'movie 1'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3974&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'movie 4'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3780&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'movie 5'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2629&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# for tv-shows
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'profile 1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"serie 1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'season 1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;'episode 1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;241&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'episode 2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3552&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s"&gt;'season 2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;'episode 1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;241&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'episode 2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3552&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'episode 3'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3512&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Viewing the data
&lt;/h2&gt;

&lt;p&gt;My goal was to generate an HTML page where I could see the data and interact with different types of visualization. But I didn't want to write strings in python that would later be written into a file. In my experience, this can make the script quite big and confusing, so I decided to use &lt;a href="https://jinja.palletsprojects.com/en/2.11.x/"&gt;Jinja&lt;/a&gt;, a "modern and designer-friendly templating language for Python, modeled after Django's templates".&lt;/p&gt;

&lt;p&gt;To use jinja you basically create a template, which in my case is a HTML file, and, on the places you want to include specific information, you call &lt;code&gt;render&lt;/code&gt;, passing the data to be replaced/added. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jinja2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileSystemLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'template.html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jinja2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'output.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variableToReplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Table
&lt;/h3&gt;

&lt;p&gt;To start I wanted a simple table with all the data. This helped me understand better the data, see what I was doing wrong, specially around extracting the information from the TV shows. With Jinja, this was pretty easy. In my HTML template file, I created a table, and added jinja's tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"watched-table"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"table table-striped table-bordered"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:100%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Profile&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Movie&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Type&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Watched time (HH:MM:SS)&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
        {% for item in watched_table %}
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{item.profile}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{item.title}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{item.type}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;data-order=&lt;/span&gt;&lt;span class="s"&gt;"{{item.total_seconds}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{item.total_time}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        {% endfor %}
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jinja accepts an array and is capable of doing the iteration on the fields. All I needed to do is create an object in the format expected (with profile, title, type, total_seconds, and total_time), and boom! The table was being built as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualization
&lt;/h3&gt;

&lt;p&gt;I wanted something like a treemap for the visualization, allowing me to see the information on different levels (user, movies/series, season, etc.). Checking the examples on D3's page, I thought the &lt;a href="https://observablehq.com/@d3/zoomable-sunburst"&gt;Zoomable Sunburst&lt;/a&gt; was a great option. Later I came to find the &lt;a href="https://bl.ocks.org/vasturiano/12da9071095fbd4df434e60d52d2d58d"&gt;Zoomable Sunburst with Labels&lt;/a&gt;, which was almost perfect.&lt;/p&gt;

&lt;p&gt;For those not familiar, D3.js is a JavaScript library for manipulating documents based on data, helping you bring data to life using HTML, SVG, and CSS. The example's page has many beautiful visualizations, and it's a sight for sore eyes!&lt;/p&gt;

&lt;p&gt;Anyway, I was able to use pretty much the same code as in the example, only changing a few things on the labels and titles. The hardest part here was actually generating the file in the expected format for d3. (I won't go into details, but you can find them in the script on &lt;a href="https://github.com/thamara/my-netflix-data/blob/master/analyze-netlflix-data.py"&gt;GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I was amazed that even though I had quite many entries (almost 40k), D3 generated the SVG image in little time. The use, however, not the smoothest, is pretty responsive.&lt;/p&gt;

&lt;p&gt;With this, I completed my first milestone for the analysis page, and you can see an example (with real data) in &lt;a href="https://thamara-my-netflix-data.netlify.app/"&gt;this page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future work
&lt;/h2&gt;

&lt;p&gt;While working, I noticed that a lot of things can be improved. Mostly new visualizations can be added, tackling portions of the available data, but I haven't worked on yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I know many people have done much more in-depth and much more complicated analysis on the Netflix data and made that available. Still, considering my personal goal of writing some python lines and work with some different technologies, this project was a great success. I had a lot of fun with the data, thinking about what I wanted to display, and especially how.&lt;/p&gt;

&lt;p&gt;I'll consider working on this a little more, improving the visualization, and making the use of the script easier (maybe publish it as a notebook?). If you have any suggestions or have any problems running the script, you can find me on &lt;a href="https://twitter.com/thamyk"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>python</category>
      <category>dataanalysis</category>
      <category>datavisualization</category>
    </item>
    <item>
      <title>How to make someone's day in under 5 min</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Thu, 15 Oct 2020 10:14:55 +0000</pubDate>
      <link>https://dev.to/thamara/how-to-make-someone-s-day-in-under-5-min-36ep</link>
      <guid>https://dev.to/thamara/how-to-make-someone-s-day-in-under-5-min-36ep</guid>
      <description>&lt;p&gt;Over the weekend, I got an email notification from someone I didn't know. The subject read, "Thank you for your GitHub post!". I got curious. This person was thanking me for one issue I fixed in my own Open Source App a few months ago in the email. That has allowed this guy to understand and resolve an issue that was blocking him for 2 weeks. This has made my day. It was amazing to know that something I was doing for my own purposes had a positive effect on someone else's life.&lt;/p&gt;

&lt;p&gt;This person probably spent less than 5 minutes writing the email, and as a side effect, caused me to be happy a whole day.&lt;/p&gt;

&lt;p&gt;Some days ago, I sent a thank you message to someone involved in the organization of the scholarships for the CppCon (I talked more about this in &lt;a href="https://thamara.github.io/blog/2020/09/24/cppcon-2020-the-halway-track/"&gt;this post&lt;/a&gt;). Just by hitting send, I felt good because I was acknowledging the effort someone (actually a lot of people) put into doing something unique that had a significant impact on me. In the reply, the person thanked me for taking the time to send it, which only made me even happier. In this email, this person also shared that often they don't hear back from people, so my message was extra-appreciated.&lt;/p&gt;

&lt;p&gt;On a personal project with a few friends, we help women build stronger resumes by giving feedback on their current CV. When we send the feedback, we also send a link for a survey on their expectations and what we could do better. As for today, we have already reviewed around 115 resumes; from those, only 25% have filled the survey. Often, those who respond are grateful for the work we've been doing. On some occasions, they even follow up thanking us for helping them be more confident and get a new work position. When this happens, it shows us we are on the right path, which makes our work totally worth it.&lt;/p&gt;

&lt;p&gt;If complimenting makes us feel better and makes the day of someone else, why don't we do it more often?&lt;/p&gt;

&lt;p&gt;I invite you to try to enforce it on your day today. Identify the people and the occasions, and give genuinely complements. It should take you less than 5 minutes and has the great potential of making the person's day.&lt;/p&gt;

&lt;p&gt;Remember, there's no size for the impact; maybe someone wrote a tweet that had a considerable effect on the way you work and live, or perhaps someone spent a lot of effort in preparing a presentation or event that you attended, and, even if the person was only "doing their job", take a few minutes and acknowledge the excellent work and make this person's day by complimenting them.&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@jacquiemunguia?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jacqueline Munguía&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/happy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Contributing to Open-Source, a brief how-to</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Sat, 10 Oct 2020 09:21:51 +0000</pubDate>
      <link>https://dev.to/thamara/contributing-to-open-source-a-brief-how-to-i36</link>
      <guid>https://dev.to/thamara/contributing-to-open-source-a-brief-how-to-i36</guid>
      <description>&lt;p&gt;October is here, so it is &lt;a href="http://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt;, an event by DigitalOcean in partnership with Intel and Dev to celebrate Open Source and get more people involved with it.&lt;/p&gt;

&lt;p&gt;As someone who found in open source a lot of fun and knowledge, I'm always talking to others to join this party. Still, usually, I get the following answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don't know Git and Github...&lt;/li&gt;
&lt;li&gt;I don't know how to program...&lt;/li&gt;
&lt;li&gt;Where do I even find a project to start with?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To answer all of that, and much more, I got together with Tulio Leão, a dear friend that shares all my excitement regarding open-source, and we hosted a virtual Meetup on Youtube to answer all of that.&lt;br&gt;
If you are a Portuguese speaker, you can check the recording &lt;a href="https://www.youtube.com/watch?v=J_HAsKN_m14&amp;amp;ab_channel=ThamaraAndrade"&gt;in here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I will cover a summary of the event, hoping it can be useful for someone who wants to start contributing to open source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;Git is the kind of skill that, doesn't matter what you do, mastering it should be useful. If you are a developer, you probably already know Git or any other form of source control, and that's great! The hardest part of learning git is understanding the concepts; if you already know something, it should be a matter of adapting to the commands.&lt;/p&gt;

&lt;p&gt;Explaining Git from the beginning should take more than one post, so I leave this to you. I suggest you start and my new favorite game-ish site &lt;a href="https://learngitbranching.js.org/"&gt;Learn Git Branching&lt;/a&gt;, where it will explain you the concepts of Git, step by step, and you can practice directly on the site (no need to worry of messing something up). &lt;a href="https://git-scm.com/book/en/v2"&gt;Git's&lt;/a&gt; own page is also a great resource, with a completely free book on git commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;As you would expect, GitHub is related to Git, in a way that it's a hosting platform for version control (usually Git) and collaboration. Basically, it's a source of repositories where multiple people can work simultaneously. Besides this, it also adds lots of functionalities to improve project management, such as an issue tracker, continuous integration, wikis, and much more. &lt;/p&gt;

&lt;p&gt;The best way to learn how to use GitHub is by actually using it. So let me walk you through what a usual work is using GitHub:&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;First of all, we need to find a project (there will be more tips at the end on how to find those)&lt;/li&gt;
&lt;li&gt;When you find one project you want, you can browse around, check the code, the issues, what people are doing, until you find something you feel comfortable taking&lt;/li&gt;
&lt;li&gt;You fork the repository to your account, kind of creating your own copy of it for you to clone and modify&lt;/li&gt;
&lt;li&gt;In your fork, you start a new branch for your modification&lt;/li&gt;
&lt;li&gt;Now it's time you start coding or doing whatever was the task you meant to do; this will become commits in your own fork of the project&lt;/li&gt;
&lt;li&gt;With your changes done, you push the commits to your fork&lt;/li&gt;
&lt;li&gt;From your fork, you open a Pull Request (or PR for simplification); this is saying to the maintainers of the project that you did something and is ready to share with them&lt;/li&gt;
&lt;li&gt;The maintainers (or actually anyone interested) will review your changes and point to some things you need to change. This step might take some time and some iterations until it's all good.&lt;/li&gt;
&lt;li&gt;With the change approved, now it's up to the project's maintainers to merge your PR, thus making it available in the standard branch of the project, and guess what?&lt;/li&gt;
&lt;li&gt;You are done!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The flow can change from project to project, but this is considered the typical case. All of this is beautifully illustrated and explained in &lt;a href="https://guides.github.com/introduction/flow/"&gt;GitHub's Understanding the GitHub flow&lt;/a&gt;.&lt;br&gt;
In my presentation, I illustrated this scenario; you can check it &lt;a href="https://github.com/codiqueijo/recursos/blob/main/2020-10-01%20-%20Uaiktoberfest/02%20-%20Uaiktoberfest%20-%20Git%2C%20GitHub%20e%20Hacktoberfest.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding is not the only skill required to contribute
&lt;/h2&gt;

&lt;p&gt;When we think about open-source, usually we imagine a developer or someone who knows to program. If you don't know, you may think open-source is not for you. Well, this is entirely incorrect. There are many different roles in projects, and for sure you can find something you can help.&lt;/p&gt;

&lt;p&gt;Here are a few examples (there are many more) of roles you can assume to contribute to open source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a user: Yes! Open source projects need users, especially those that are willing to give feedback on the project. This can be opening issues, proposing enhancements, and a lot more. As a user, you are not required to understand a single line of the code or the project's infrastructure.&lt;/li&gt;
&lt;li&gt;As a manager: Most projects have some sort of a software development process established in terms of releases, task organization, features prioritization, and more. You can help to manage it, with a higher-level view of deliveries and again, without actually needing to code a thing.
As a translator: Lots of projects have a way of localizing its content. You can help translate it to the languages you are familiar with or even just reviewing previous translations.&lt;/li&gt;
&lt;li&gt;As an artist: At some point in my life, I heard that developers don't know how to draw. Although I disagree this is true, many projects out there will benefit from someone with a more artistic view. This means that there are tasks for you to work on the branding or on specific components that need an artsy touch.&lt;/li&gt;
&lt;li&gt;As a documentarian: if there is something that any project is missing at some level, it is documentation, not only on the code itself. We are talking about the documentation of the tool or whatever is the product of the project.&lt;/li&gt;
&lt;li&gt;As a reviewer: Code reviews are essential, and on the open-source, I think it's vital. But many times, the maintainers of the project cannot undertake all the work, and you can help them by doing reviews!&lt;/li&gt;
&lt;li&gt;As a developer: that's the obvious one, but it's not apparent that you don't need lots of experience in a language/technology to contribute. You can even use it as a way for you to improve your skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where to start
&lt;/h2&gt;

&lt;p&gt;Finding a project to start is maybe the most challenging step when we talk about open source. My first suggestion is to check the products you already use; chances are that some of those are open source. Because you already use them, it will be easier to understand the project's scope and intent. Sometimes this can be a little challenging, so there are other paths.&lt;/p&gt;

&lt;p&gt;Under a project on GitHub, you'll find that the issues have different labels, some of those with great names such as "good-first-issue" or "first-contributors", and more, indicating those that are more straightforward tasks that you can work on to get you more comfortable with the project and the flow.&lt;/p&gt;

&lt;p&gt;You can search for these labels directly on GitHub, or you can check the pages below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://up-for-grabs.net/#/"&gt;Up for grabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://goodfirstissues.com/index.html"&gt;Good First Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MunGell/awesome-for-beginners"&gt;Awesome for Beginners&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As this is my post, I can do some advertising some of my own projects too, right?!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/thamara/time-to-leave"&gt;Time to Leave&lt;/a&gt;: A working hours tracker that notifies you when it's time to leave. It's based on Electron and written in JavaScript. You can help with development, translation, testing, and whatever you feel like, really.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/thamara/vscode-code-annotation"&gt;Code Annotation, a VSCode exntension&lt;/a&gt;: A VSCode extension that allows you to create annotations (like todos) on your code, without actually committing the changes. As this is something, I have started recently, any kind of help is welcome!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I hope this has inspired you a little bit more to contribute to open source. I've been actively contributing to several projects, including creating my own for more than a year now, and I can't even measure how much I learned during this time. Especially over the past months, due to Corona and such, this has been the hobby that has helped me keep my sanity.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to get in touch on Twitter over &lt;a href="https://twitter.com/thamyk"&gt;@thamyk&lt;/a&gt;. I would be glad to help you on this journey!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>git</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>What if I need to make a change in node_modules?</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Fri, 11 Sep 2020 01:46:49 +0000</pubDate>
      <link>https://dev.to/thamara/what-if-i-need-to-make-a-change-to-nodemodules-o8e</link>
      <guid>https://dev.to/thamara/what-if-i-need-to-make-a-change-to-nodemodules-o8e</guid>
      <description>&lt;p&gt;I have an application build on top of node/electron, and recently, because of an update in the electron, some dependencies have broken down, preventing me to upgrade to the newer versions while keeping all functionalities.&lt;/p&gt;

&lt;p&gt;In such cases, the correct behavior would be to reach out to the dependency, and open an issue, or even submit a Pull Request, but what if your dependency is not maintained anymore, or the development process on such repository is stalled or slow, and you really need to move on with your development?&lt;/p&gt;

&lt;p&gt;That was the scenario I was facing. The change I needed was very localized, but I could not, in a million tries, get to make it work on my fork of the dependency. To make things worst, the last commit on the repository was over 6 months ago, and no sign of a reply on the issue I opened in a week.&lt;/p&gt;

&lt;p&gt;That's when I found &lt;a href="https://github.com/ds300/patch-package" rel="noopener noreferrer"&gt;patch-package&lt;/a&gt;, a package that lets app authors instantly make and keep fixes to npm dependencies.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ds300" rel="noopener noreferrer"&gt;
        ds300
      &lt;/a&gt; / &lt;a href="https://github.com/ds300/patch-package" rel="noopener noreferrer"&gt;
        patch-package
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fix broken node modules instantly  🏃🏽‍♀️💨
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/349620bcaddda01b96789beb7aa9b4dc6c8684be9a797116038be00ee159267b/68747470733a2f2f64733330302e6769746875622e696f2f70617463682d7061636b6167652f70617463682d7061636b6167652e737667"&gt;&lt;img src="https://camo.githubusercontent.com/349620bcaddda01b96789beb7aa9b4dc6c8684be9a797116038be00ee159267b/68747470733a2f2f64733330302e6769746875622e696f2f70617463682d7061636b6167652f70617463682d7061636b6167652e737667" width="80%" alt="patch-package"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;patch-package&lt;/code&gt; lets app authors instantly make and keep fixes to npm
dependencies. It's a vital band-aid for those of us living on the bleeding edge.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; fix a bug in one of your dependencies&lt;/span&gt;
vim node_modules/some-package/brokenFile.js
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; run patch-package to create a .patch file&lt;/span&gt;
npx patch-package some-package

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; commit the patch file to share the fix with your team&lt;/span&gt;
git add patches/some-package+3.14.15.patch
git commit -m &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;fix brokenFile.js in some-package&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Patches created by &lt;code&gt;patch-package&lt;/code&gt; are automatically and gracefully applied when
you use &lt;code&gt;npm&lt;/code&gt;(&amp;gt;=5) or &lt;code&gt;yarn&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;No more waiting around for pull requests to be merged and published. No more
forking repos just to fix that one tiny thing preventing your app from working.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Set-up&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;In package.json&lt;/p&gt;
&lt;div class="highlight highlight-source-diff notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt; "scripts": {
&lt;span class="pl-mi1"&gt;&lt;span class="pl-mi1"&gt;+&lt;/span&gt;  "postinstall": "patch-package"&lt;/span&gt;
 }&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;npm&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm i patch-package
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can use &lt;code&gt;--save-dev&lt;/code&gt; if you don't need to run npm in production, e.g. if
you're making a web frontend.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ds300/patch-package" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;a href="https://github.com/ds300/patch-package/blob/master/README.md" rel="noopener noreferrer"&gt;README&lt;/a&gt; has all the information you'll need, but I'll summarize here the idea: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install patch-package (using npm or yarn)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the &lt;code&gt;scripts&lt;/code&gt; rule on your &lt;code&gt;package.json&lt;/code&gt; to include a call for patch-package:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 "scripts": {
+  "postinstall": "patch-package"
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
3. Do the change you need on the dependency, directly on node_modules
4. Call patch-package specifying the package you modified:

    ```


    (npx | yarn) patch-package package-name


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The last command will create a patch file (a diff) in `patches/`, which is a diff between the public dependency and your changed version.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Commit the changes, including the new patch file and everything will be working as expected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, whenever you (or someone) calls install on your repository, patch-package will be called, applying that change on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/5oGIdt1xapQ76/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/5oGIdt1xapQ76/giphy.gif" alt="Win!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem solved!&lt;/p&gt;

&lt;p&gt;What about you? Have you ever needed to take a similar action?&lt;/p&gt;

</description>
      <category>node</category>
      <category>electron</category>
      <category>npm</category>
    </item>
    <item>
      <title>We are not all guys, we are not all he</title>
      <dc:creator>Thamara Andrade</dc:creator>
      <pubDate>Wed, 09 Sep 2020 04:30:53 +0000</pubDate>
      <link>https://dev.to/thamara/we-are-not-all-guys-we-are-not-all-he-1n69</link>
      <guid>https://dev.to/thamara/we-are-not-all-guys-we-are-not-all-he-1n69</guid>
      <description>&lt;p&gt;I have to warn you, if you don't already know the issue with "guys", you are about to, and this will forever change you.&lt;br&gt;
This is an outburst that many women and non-binary people might relate to, and I ask for the men who found this to continue reading and empathize with the cause.&lt;/p&gt;

&lt;h1&gt;
  
  
  So, what's the problem with "Guys"
&lt;/h1&gt;

&lt;p&gt;tl; dr;: &lt;a href="https://heyguys.cc/"&gt;heyguys.cc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, the problem is that "guys", is not as inclusive as you think. People who aren't men can feel excluded when addressed as "guys," even if that is not the intent. And, from the moment you (especially if you are not a man) realize this, forever you'll feel discomfort when people say the two words "hey guys" (and all its variations).&lt;br&gt;
The problem is even worst when we have it in the singular form. Recently I heard "I will take this to the RD guy", but I was the RD person, me, a woman, and the person who said it knew that. It bothered me. And we see this kind of thing every day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/UuB5mPL27mn3UbF4pO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/UuB5mPL27mn3UbF4pO/giphy.gif" alt="My prefered"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;At a glance, the solution is simple: replace guys with other words, or get rid of that for complete.&lt;br&gt;
"Hey guys", can become "Hey folks", "RD guy" can easily be replaced by just "RD". And in the cases where you want to specify a group, why not replace "RD guys" by developers?!&lt;/p&gt;

&lt;p&gt;The difficult part here is that we are used to these sayings, and changing them requires a mental effort and some attention. Kate Gregory goes deeper into this issue, even pointing out that "people" also means "men" in her post &lt;a href="http://www.gregcons.com/KateBlog/ThoughtsAboutGuys.aspx"&gt;Thoughts about "guys"&lt;/a&gt;, which I highly suggest you read. In there she concludes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The hard part isn’t figuring out how to reword the sentence to avoid the word guy or guys. The hard part is breaking the habit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What about the "he"?
&lt;/h1&gt;

&lt;p&gt;How many times you heard or read something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each user of the program will input his login and password.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice anything strange? I'll point to you in case you missed: We are using "his" as the pronoun for "user", even though we want to be generic.&lt;br&gt;
This happens a lot, and if you are not a he, you'll probably notice that already.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;You could rephrase your sentences saying "he or she", or "his or her", which is a much better option, but something that has been gaining some space in the English language, is the use of the &lt;a href="https://en.wikipedia.org/wiki/Singular_they"&gt;singular they&lt;/a&gt;. The singular they, as the name suggests, is the use in of the pronoun they or its inflected or derivative forms, as a gender-neutral singular pronoun.&lt;br&gt;
I'm extremely pro the use of the singular they, but there might be some public that dislikes it, so its usage is not well established yet. If you feel this is the case of the public you usually speak to, there are alternatives still.&lt;/p&gt;

&lt;p&gt;In the article of &lt;a href="https://techwhirl.com/gender-neutral-technical-writing/"&gt;Gender-neutral Technical Writing&lt;/a&gt; by Tech Whirl, we have several suggestions on how to have a gender-neutral vocabulary, without butchering the language. Here are a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bypass the problem of gender whenever possible: Use imperative mood when talking directly to the user (usually in instructional manuals) or use second person instead of the third person (you vs he/she)&lt;/li&gt;
&lt;li&gt;Use plural nouns and plural pronouns instead of their single counterpart&lt;/li&gt;
&lt;li&gt;Avoid pronouns completely when you can&lt;/li&gt;
&lt;li&gt;Use generally-accepted titles: engineers, programmers, users, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Last thoughts
&lt;/h1&gt;

&lt;p&gt;For those who reached here, thank you for listening. At first sight, these might look like ridiculous rants, but the ugly truth is that this is just another example of how (especially) the tech industry is not an inclusive place. Paying attention to the language is a small step towards a better and diverse ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/h8IcERBmFXChSSKlNI/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/h8IcERBmFXChSSKlNI/giphy.gif" alt="Our diversity is out power"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After reading, tell me, what do you think of this?&lt;/p&gt;

&lt;p&gt;Title partially borrowed by &lt;a href="https://twitter.com/ClareMacraeUK/status/700259853365858304"&gt;Clare Macrae&lt;/a&gt;.&lt;br&gt;
&lt;span&gt;Cover photo by &lt;a href="https://unsplash.com/@climatereality?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;The Climate Reality Project&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/meeting-men?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>tech</category>
      <category>it</category>
      <category>letstalk</category>
    </item>
  </channel>
</rss>
