<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2021-04-05T11:21:42+00:00</updated><id>/feed.xml</id><title type="html">Smlep</title><subtitle>Welcome to my Github page, a place where I post about the open-source projects you can find on my GitHub.</subtitle><entry><title type="html">Building a three-player chess website</title><link href="/jekyll/update/2020/12/26/yaltachess.html" rel="alternate" type="text/html" title="Building a three-player chess website" /><published>2020-12-26T00:00:00+00:00</published><updated>2020-12-26T00:00:00+00:00</updated><id>/jekyll/update/2020/12/26/yaltachess</id><content type="html" xml:base="/jekyll/update/2020/12/26/yaltachess.html">&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;

&lt;p&gt;Around the end of 2019, as we were going through our few last months of
engineering school, we ended up having a quite consequent amount of free
time due to the highly irregular organisation of courses throughout the year.&lt;/p&gt;

&lt;p&gt;Daniel, a friend of mine from school who has
been a huge fan of chess for a while now told us one night about how he read 
about this chess variant with three players and how he thought it would be
interesting to build a game engine for it.&lt;/p&gt;

&lt;p&gt;Since I had time to &lt;del&gt;waste&lt;/del&gt; spend building something &lt;del&gt;funny&lt;/del&gt; meaningful,
I was interested in getting involved in this project to make it grow and be
something more than only a game engine (which I thought nobody would use
anyway, since playing chess through command line on a single computer does not
seem that appealing).&lt;/p&gt;

&lt;p&gt;That’s how, Daniel, Vincent (another friend from school with whom I had
worked on many side projects), and I decided that we were going to build a
website so that people could come and play chess with two of their
friends.&lt;/p&gt;

&lt;h2 id=&quot;what-is-three-player-chess&quot;&gt;What is three-player chess?&lt;/h2&gt;

&lt;p&gt;Some might wonder what really is 3-player chess, do the rules change
when introducing a third player, and if they do, how?&lt;/p&gt;

&lt;p&gt;Even though 3-player chess seems like a simple and precise concept, there are many variations
with light differences and not one set of rules for 3-player chess. These different
variations come in variants with different names (Trichess, Chess for three, Three-Player
Chess, Yalta chess…) but not every mention of one variant describes the same rules and
there is a huge lack of norm here.&lt;/p&gt;

&lt;p&gt;The variation of chess played on &lt;a href=&quot;https://yalta-chess.com&quot;&gt;yalta-chess.com&lt;/a&gt; can be
considered as a unique variant, but mostly inspired by &lt;strong&gt;Yalta Chess&lt;/strong&gt; (not much suspense
here) from which we tried to follow the rules as much as possible, but once again, the rules
differed depending on the articles.&lt;/p&gt;

&lt;p&gt;On our website, you’ll play on a 96-cell board (32 for each player, just like usual chess).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/yalta-animation4.gif&quot; alt=&quot;Yalta board&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The moves are the same as classic chess, but it can take some time to get used to the
moves around the center or the board when starting to play &lt;strong&gt;Yalta Chess&lt;/strong&gt;. The only real difference
with 2-player chess is how winners and losers are handled.&lt;/p&gt;

&lt;p&gt;The winner is the first player to checkmate another player, meaning that there are one
winner and two losers. This makes the game more interesting, rewarding aggressive strategies
since playing too defensive might end up in a loss where one of the other players checkmated
the third player.&lt;/p&gt;

&lt;h2 id=&quot;early-development&quot;&gt;Early development&lt;/h2&gt;

&lt;p&gt;Our initial goal was pretty simple and seemed easy to accomplish, the
tasks which needed to be done could have been summed up as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Building a game engine, implementing every rule and move.&lt;/li&gt;
  &lt;li&gt;Having a game page on which 3 players could play together with a decent user
experience.&lt;/li&gt;
  &lt;li&gt;Having a basic matchmaking system, so that players could join games easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looked easy and fast, the game engine was the main challenge since the special
shape of the board made the classic 2-player chess implementation unsuitable for
our needs and we needed to come up with a smart way to handle the board. Once the
game engine was out of the way, the only remaining thing would be to build a simple
website with basic functionalities.&lt;/p&gt;

&lt;p&gt;Two of us already had some web development knowledge which we acquired through previous
side-projects, I would not say that we were &lt;strong&gt;amazing&lt;/strong&gt; (or good) web developers,
but we were at least decent. Well, for the backend at least, our UI/UX level was (and
still is, but those who saw the website already know that) pretty bad.&lt;/p&gt;

&lt;p&gt;Since we weren’t looking for high performances in our game engine because a few
milliseconds were not going to impact the user experience, building the engine was
actually pretty fast. One of us focused on it, and after a few days we had a game engine
implementing the rules and about everything we needed except &lt;em&gt;promotions&lt;/em&gt;, &lt;em&gt;castling&lt;/em&gt;, and
&lt;em&gt;en passant&lt;/em&gt; which came later.&lt;/p&gt;

&lt;p&gt;Our implementation relied on the fact that instead of using one 8x8 board as in 2-player
chess, we considered the board as 3 distinct 4x8 sub-boards, each sub-board filled with a
different color on the example below: 
&lt;img src=&quot;/assets/yalta-subboards.png&quot; alt=&quot;Yalta debug mode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The website, on the other hand, was way more complicated than we anticipated, handling
concurrent plays with real-time information transfer between the players (without
refreshing after each move) and implementing a decent user experience was much more
challenging than we expected.&lt;/p&gt;

&lt;p&gt;Our first playable version looked like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/yalta-debug.gif&quot; alt=&quot;Yalta debug mode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With the three boards representing the three sides of the board as explained above.&lt;/p&gt;

&lt;p&gt;This first version allowed us to check that our engine worked as intended, but
required us to refresh a page to see the other players’ moves and wasn’t very user friendly.&lt;/p&gt;

&lt;p&gt;That’s when we really became aware that the website part of the project would require
an amount of work strongly higher than the game engine implementation.&lt;/p&gt;

&lt;h2 id=&quot;a-basic-project&quot;&gt;A basic project&lt;/h2&gt;

&lt;p&gt;The more we implemented new features on our website, the more features we thought about
which seemed to be required to have a decent user experience on the website. Some of these features
were not necessary but seemed like good ideas/interesting to implement so we implemented some of them
and the others were listed and put aside for later.&lt;/p&gt;

&lt;p&gt;After a few weeks, we had a decent result for the play part of the website; three players could
play on the same page, moving by selecting a piece and moving it to its location and seeing the actions’
results in real-time.&lt;/p&gt;

&lt;p&gt;Our first &lt;em&gt;matchmaking&lt;/em&gt; system was fairly basic, there was a list of created games, and any player
could join any game, if the user was the third player to join a game, it would start, and if there were
3 players already in the game, the user would be considered as a spectator. On top of that, any user
could create a new game.&lt;/p&gt;

&lt;p&gt;At this time we had already spent way more time on this project than we thought we were going to,
even though we had only implemented the features we thought were necessary to have a good time
playing the game. The website’s current state was enough to send the link to some friends and play
games with them if we wanted to, the global design of the website wasn’t nice, but playing stayed pretty intuitive.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/yalta-landing-1.png&quot; alt=&quot;Landing page&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;not-so-basic-anymore&quot;&gt;Not so basic anymore&lt;/h2&gt;

&lt;p&gt;When we started this project, we did not define the real scope of users who would use it,
the more we worked on it and the more features we started implementing, the more we started to
want to make it public so that everyone could come and play.&lt;/p&gt;

&lt;p&gt;As we started having less free time due to school projects and then the real jobs we got
after graduating, we spent way less time developing this project the following months but we kept working
on it and added a lot of new sfeature. Some of those being necessary for a public release,
some that we felt were a really nice addition for users and some which might just be
really useless (Hello, in-game chat). Among these extra-features are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A custom game system to play with friends with custom settings&lt;/li&gt;
  &lt;li&gt;A public queue system to play with random unknown players&lt;/li&gt;
  &lt;li&gt;A training mode to play against bots in different difficulties&lt;/li&gt;
  &lt;li&gt;A profile system with ranks, elo, skins, themes, and statistics&lt;/li&gt;
  &lt;li&gt;Game timers&lt;/li&gt;
  &lt;li&gt;A board rotation system, to see the board as one of your opponents&lt;/li&gt;
  &lt;li&gt;An in-game chat&lt;/li&gt;
  &lt;li&gt;The possibility to show replays of games&lt;/li&gt;
  &lt;li&gt;A documentation section to explain the website and the game rules&lt;/li&gt;
  &lt;li&gt;A landing page to explain to new users what happens here&lt;/li&gt;
  &lt;li&gt;A new implementation of the game engine with improved performances
and a graph system (replacing the 3x4x8 sub-boards implementation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And of course, a landing page to welcome new players to our website.
The old matchmaking system based on a game list was removed, since the public
queue and private game system fully replaced the need for it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/yalta-ways-to-play.png&quot; alt=&quot;Ways to play&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;costs-and-revenues&quot;&gt;Costs and revenues&lt;/h2&gt;

&lt;p&gt;As we added new features and new services which started to increase potential costs, we had to
consider the &lt;em&gt;business&lt;/em&gt; aspect of the website. We were not fully against trying to monetize it but
we did not want this to impact the user experience, driving potential users away because of
&lt;em&gt;aggressive advertising&lt;/em&gt; or &lt;em&gt;pay-to-win&lt;/em&gt; systems.&lt;/p&gt;

&lt;p&gt;We considered &lt;strong&gt;ads&lt;/strong&gt;, but generic ads (such as adsense) would require to have a huge 
amount of traffic to really generate money and they usually don’t fit well into a website. We did
not want our website to get significantly less enjoyable for users just to win a few euros every month (or year).&lt;/p&gt;

&lt;!--
Another thing we considered was to bring premium content to the website, allowing users to purchase
differents assets such as skin. The issue with this solution is that it is really hard to find good
content which will not impact the other users impact experience.
We did implement a skin system, so that players could update the apparences of their pieces, so that
we could set up a system where the users would be able to buy these apparences. But the impact on the
other players which were just trying to focus would be too high, who wants to start a game and be
matched again a player with flashy purple pieces?
There are options to prevent this scenario such as adding a button to hide every opponents skin, but
players won't buy skins if the other players can't see it.
--&gt;

&lt;p&gt;We considered some other solutions than ads but in the end, &lt;strong&gt;we did not find an adequate business model&lt;/strong&gt;.
Not being able to generate revenue is not currently an issue, since the goal never was to quit our jobs and
start working on this project every day of the week. Nevertheless, we did not anticipate when we started this
project (before we decided to add many unexpected features) that there were gonna be real costs to run
the website.&lt;/p&gt;

&lt;p&gt;Indeed, the website now runs using many different services and tools which come with a cost, meaning
that we cannot sustain with this business model (which is not one, since we generate no revenue) if
our user count grows too much.&lt;/p&gt;

&lt;p&gt;As long as our monthly costs stay under a few dozen of euros, it is
fine, I’d say that we are happy to pay for it if some people are happy to play on
&lt;a href=&quot;https://www.yalta-chess.com/&quot;&gt;yalta-chess.com&lt;/a&gt;. But if this website became too popular, we would have
to scale up the different services we pay for (hosting, Redis, database…), resulting in hundreds of
euros bills.&lt;/p&gt;

&lt;p&gt;Hence, if too many people end up enjoying our website, at some point we will have to &lt;strong&gt;shut it
down&lt;/strong&gt; (or strongly restrict traffic) if we still cannot generate revenue.&lt;/p&gt;

&lt;p&gt;This is really &lt;strong&gt;unlikely&lt;/strong&gt; to happen since we don’t plan on doing real advertising for this project,
and we are not so presumptuous as to think that this website is good enough to deserve this much 
success. But we still have to consider this scenario, and if it happens we will still try to consider
ways to generate revenue, we are not fully closed to ads, but we feel like right now nothing fits our
needs, maybe we’ll set up a donation  system but those rarely work.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/yalta-profile.png&quot; alt=&quot;Profile page&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;We probably spent too much time on this website, way too much, but most features were
implemented because we &lt;strong&gt;enjoyed&lt;/strong&gt; it and not really because we felt like all of them were required.&lt;/p&gt;

&lt;p&gt;We still have dozens of ideas about improvements that could be implemented for this project which
could make me work on this project for a few extra months or years.
But I thought it was time to wrap it up and prepare everything needed for a public release, putting
all remaining ideas into an issue list with implementation ideas if a &lt;strong&gt;V2&lt;/strong&gt; came to be
implemented one day.&lt;/p&gt;

&lt;p&gt;This will make this project feel like a &lt;em&gt;complete&lt;/em&gt; product (even though I know it’s not), allowing me
to move on to other side-projects.&lt;/p&gt;

&lt;!--
Of course I know that releasing the website cannot mean that my work on it is over and that I can
fully stop working on it, because if it gets some success, I'll have to spend hours monitoring it
and fixing bugs, and even though we tried to build it to scale, it never is that easy.
--&gt;

&lt;p&gt;Come try the website at &lt;a href=&quot;https://yalta-chess.com&quot;&gt;yalta-chess.com&lt;/a&gt;, if you don’t find any players
in the public queue and you don’t have any friends to play private games with, head to the
&lt;a href=&quot;https://www.yalta-chess.com/private-queue?toggleTraining=yes&quot;&gt;training section&lt;/a&gt;
(Create a custom game =&amp;gt; Training) and try playing against our bots with various difficulties.&lt;/p&gt;

&lt;p&gt;A special thanks to &lt;a href=&quot;https://github.com/danielbaud&quot;&gt;Daniel&lt;/a&gt; and 
&lt;a href=&quot;https://github.com/Choqs&quot;&gt;Vincent&lt;/a&gt; for working with me on some parts
of the project and for their continuous reviews of the website’s progression.&lt;/p&gt;

&lt;p&gt;If you want to get in touch about this project, feel free to contact me at smlep@yalta-chess.com.&lt;/p&gt;</content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html">Context</summary></entry><entry><title type="html">Internship: Resume and Career</title><link href="/jekyll/update/2019/10/05/myresume.html" rel="alternate" type="text/html" title="Internship: Resume and Career" /><published>2019-10-05T00:00:00+00:00</published><updated>2019-10-05T00:00:00+00:00</updated><id>/jekyll/update/2019/10/05/myresume</id><content type="html" xml:base="/jekyll/update/2019/10/05/myresume.html">&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;

&lt;p&gt;To complete my Master in Data Science I’m doing at
&lt;a href=&quot;https://www.epita.fr/&quot;&gt;EPITA&lt;/a&gt;, I’m now looking for
an internship in Machine Learning / Data science.&lt;/p&gt;

&lt;h2 id=&quot;education&quot;&gt;Education&lt;/h2&gt;

&lt;h1 id=&quot;epita&quot;&gt;EPITA&lt;/h1&gt;

&lt;p&gt;EPITA is a five year engineering school specialized in computer science, for
the fourth and fifth year, I am now studying Data Science and Computer Vision.&lt;/p&gt;

&lt;p&gt;At school I worked on a lot of small projects in Python, C#, Java, C, C++ and
Scala which brought me a good knowledge on many programming languages, and nice
overall algorithms skills.&lt;/p&gt;

&lt;p&gt;I started studying there in September 2015, and will be graduated in September
2020, after completing my end-of-studies internship.&lt;/p&gt;

&lt;h1 id=&quot;griffith-college-dublin&quot;&gt;Griffith College Dublin&lt;/h1&gt;

&lt;p&gt;In 2017, for the second semester of my second year at EPITA, I had the
opportunity to spend one semester abroad and I chose to go to Dublin from
January 2017 to June of the same year.&lt;/p&gt;

&lt;p&gt;There, I studied Computer Science, including algorithms, java, and android
mobile development. It was a good opportunity to study in an English environment
and to learn a new culture.&lt;/p&gt;

&lt;h2 id=&quot;experience&quot;&gt;Experience&lt;/h2&gt;

&lt;h1 id=&quot;teaching-assistant-for-third-year-students&quot;&gt;Teaching Assistant for third year students&lt;/h1&gt;

&lt;p&gt;Starting in January 2019, I became a teaching assistant for the third year
students at EPITA.&lt;/p&gt;

&lt;p&gt;As an assistant, my job was working with a team of 53 assistants managing a promotion of 600
third year students:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Redaction of programming subjects.&lt;/li&gt;
  &lt;li&gt;Creation of tutorials, bringing knowledge to students on multiple languages (C++/C/Java/SQL/UNIX).&lt;/li&gt;
  &lt;li&gt;Helping the students to fulfill the tutorials and subjects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside this big team, some of us had roles, which meant having bigger responsibilities
and a bigger amount of work. My role was to be the quality manager inside the team:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Inspection of the coherence, the feasibility and the form of the subjects created by the team.&lt;/li&gt;
  &lt;li&gt;Handling of review and help sessions for the other assistants when they have to do a presentation to the students.&lt;/li&gt;
  &lt;li&gt;Accountable for the quality of everything produced by the assistants for the students.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This job was divided in two different parts, the first one, went from January
to July and consisted in teaching C++, Java and SQL inside a smaller team (only
32 assistants) with a smaller amount of students (about 400), and the second
one started in August 2019 and is expected to last until January 2020, where
the taught languages were C and Shell, the team was bigger (53 assistants) and
the amount of students too (more than 600).&lt;/p&gt;

&lt;p&gt;I did this job in parallel to my studies, and it brought me a lot of knowledge
about the languages I taught and how to work with a team in a complex
infrastructure with interesting subjects to work on.&lt;/p&gt;

&lt;h1 id=&quot;back-end-developer-at-brainsonic&quot;&gt;Back-End developer at Brainsonic&lt;/h1&gt;

&lt;p&gt;From September 2018 to January 2019, I did an internship in a marketing agency
in Paris called Brainsonic.&lt;/p&gt;

&lt;p&gt;Brainsonic is an agency specialized in content creation and social media with
many teams working on different kind of projects, such as Brand Content, Social
Media handling, Events, and the web department.&lt;/p&gt;

&lt;p&gt;There, I was an intern with two main goals: to help with the development of
many web projects for different clients such as Microsoft, NestléWaters, SNCF
or Elior. The second one was to do some research on an emerging technologies
called Progressive Web Apps.&lt;/p&gt;

&lt;p&gt;During this internship I worked on many web technologies, the ones I used most
were PHP, HTML, CSS, JavaScript, Service Workers, Heroku, Symfony and Webpack.&lt;/p&gt;

&lt;h1 id=&quot;teaching-assistant-for-first-year-students&quot;&gt;Teaching Assistant for first year students&lt;/h1&gt;

&lt;p&gt;From September 2017 to June 2018, I was a teaching assistant in Caml and C# for 
the first year students at EPITA:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Supervising programming practice sessions&lt;/li&gt;
  &lt;li&gt;Correction of the students submissions&lt;/li&gt;
  &lt;li&gt;Creation of subjects for practice sessions and exams&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/assets/resume.pdf&quot;&gt;resume&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Smlep&quot;&gt;github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/sam-courtemanche-ba61b4136/&quot;&gt;linkedin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.kaggle.com/samlep&quot;&gt;kaggle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html">Context</summary></entry><entry><title type="html">Writing a simple program to gather news from various APIs</title><link href="/jekyll/update/2019/02/01/smlepnews.html" rel="alternate" type="text/html" title="Writing a simple program to gather news from various APIs" /><published>2019-02-01T00:00:00+00:00</published><updated>2019-02-01T00:00:00+00:00</updated><id>/jekyll/update/2019/02/01/smlepnews</id><content type="html" xml:base="/jekyll/update/2019/02/01/smlepnews.html">&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;

&lt;p&gt;During January, I had a lot of spare time compared to what I usually have: I
had just finished my fourth year internship and was waiting to really resume
the lectures I had at school.&lt;/p&gt;

&lt;p&gt;So I decided to work on another small project because I really enjoyed working
on my last open-source project (you can take a look at what I wrote on
&lt;a href=&quot;/jekyll/update/2018/10/31/spacingChecker.html&quot;&gt;SpacingChecker&lt;/a&gt; a few months
ago).&lt;/p&gt;

&lt;h2 id=&quot;finding-what-to-work-on&quot;&gt;Finding what to work on&lt;/h2&gt;

&lt;p&gt;The first main step of working on this project was to find what kind of project
I wanted it to be. All I knew is that I wanted to work on something different
from &lt;a href=&quot;https://github.com/Smlep/SpacingChecker&quot;&gt;SpacingChecker&lt;/a&gt;, that meant
no complex regular expression checking in shell, and more precisely no shell at
all.&lt;/p&gt;

&lt;p&gt;I didn’t really have more constraints or things I did not want to do, that
left me with plenty of choice about what to create, so I started to think about
what I thought I needed.&lt;/p&gt;

&lt;p&gt;A few months before that, I started to get interested about startups and new
tech products, so I tried to make a habit of staying up-to-date with tech news
and innovations.&lt;/p&gt;

&lt;p&gt;To do so, I spent a few minutes a day on
&lt;a href=&quot;https://www.producthunt.com/&quot;&gt;Product Hunt&lt;/a&gt; and
&lt;a href=&quot;https://github.com/explore&quot;&gt;GitHub&lt;/a&gt; and I found some really interesting
products and open-source softwares, some that I still use today (like
&lt;a href=&quot;https://justgetflux.com/&quot;&gt;f.lux&lt;/a&gt; for example). In the beginning, I really
enjoyed that, but after some time, some day it really started to feel like a
chore and it became harder to stay up-to-date.&lt;/p&gt;

&lt;p&gt;So I decided to create a tool which would make this easier for me, and that’s
how I started my own news aggregator.&lt;/p&gt;

&lt;h2 id=&quot;preparation-steps&quot;&gt;Preparation steps&lt;/h2&gt;

&lt;h1 id=&quot;where-should-my-news-come-from&quot;&gt;Where should my news come from?&lt;/h1&gt;

&lt;p&gt;First, I did a small list of what I wanted to have in my aggregator, and
I knew I would add more features later if I had enough time/motivation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.producthunt.com/&quot;&gt;Product Hunt&lt;/a&gt;: A must have for me, a good
place to find new softwares and websites.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/explore&quot;&gt;GitHub&lt;/a&gt;: The GitHub’s explore section is really
nice to stay updated with the last popular open-source projects.&lt;/li&gt;
  &lt;li&gt;A way to have global world news, not only tech news because geek life can
only get you so far :wink:.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;what-technologies-should-i-use&quot;&gt;What technologies should I use?&lt;/h1&gt;

&lt;p&gt;So, in the end, what I had to do was make calls to some APIs, maybe do some
scraping, and then find a way to bring this information to me simply (command
line tool, website, or e-mails were the first solutions I thought about).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; seemed like an obvious choice to me, since I knew well this language, it
was going to be easy to make calls to an API, to scrap websites, to send
e-mails or even to display the information I gathered on a website (I had a
good Django background).&lt;/p&gt;

&lt;p&gt;Moreover, I enjoyed writing code in &lt;strong&gt;Python&lt;/strong&gt; for some popular reasons such as the
ability to write code fast, the light syntax and the huge amount of
already existing packages.&lt;/p&gt;

&lt;h2 id=&quot;starting-to-gather&quot;&gt;Starting to gather&lt;/h2&gt;

&lt;p&gt;Once (almost) everything was decided, I was able to start gathering data.&lt;/p&gt;

&lt;h1 id=&quot;product-hunt&quot;&gt;Product Hunt&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://www.producthunt.com/&quot;&gt;Product Hunt&lt;/a&gt; was the first website where I
tried to gather data, my goal was to get the links and information for the most
popular products each day so that I could easily see if I found any of them
interesting, and if I did, access to more details by following the link to the
owner’s website.&lt;/p&gt;

&lt;p&gt;Product Hunt gives the users access to an
&lt;a href=&quot;https://API.producthunt.com/v1/docs&quot;&gt;API&lt;/a&gt; which can be used to make
simple read-only requests as long as you have an access_token. This token can
be obtained by creating an account and going to the &lt;a href=&quot;https://API.producthunt.com/v2/oauth/applications&quot;&gt;API
dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, anyone can access the top posts of each day to gather the &lt;strong&gt;names&lt;/strong&gt;,
the &lt;strong&gt;taglines&lt;/strong&gt;, the number of &lt;strong&gt;votes&lt;/strong&gt; and the product’s &lt;strong&gt;urls&lt;/strong&gt;.&lt;/p&gt;

&lt;h1 id=&quot;github&quot;&gt;GitHub&lt;/h1&gt;

&lt;p&gt;The second website where I liked to find news was
&lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;, I really like open-source and learning new
technologies, so I felt like going through the most popular repositories daily
would be a good way to stay up-to-date.&lt;/p&gt;

&lt;p&gt;GitHub also provides an &lt;a href=&quot;https://developer.github.com/v3/&quot;&gt;API&lt;/a&gt; which does not
require authentication to execute read-only requests with a limit of 60
requests per hour. Of course, by being authenticated, you can execute more
complex requests and with more requests per hour, but for what I had to do,
there was no need to be authenticated.&lt;/p&gt;

&lt;p&gt;What I did was requesting the most popular repositories from the last 24 hours
and extract basic information about them: the &lt;strong&gt;names&lt;/strong&gt;, the &lt;strong&gt;descriptions&lt;/strong&gt;,
the &lt;strong&gt;authors&lt;/strong&gt; and the number of &lt;strong&gt;stars&lt;/strong&gt;.&lt;/p&gt;

&lt;h1 id=&quot;global-news-the-guardian-and-le-figaro&quot;&gt;Global News: The Guardian and Le Figaro&lt;/h1&gt;

&lt;p&gt;For the news, I first started to use
&lt;a href=&quot;https://www.theguardian.com/&quot;&gt;The Guardian&lt;/a&gt;, since it has a nice
&lt;strong&gt;API&lt;/strong&gt; which can be used by getting an API key by registering
&lt;a href=&quot;https://open-platform.theguardian.com/&quot;&gt;there&lt;/a&gt;. The API is easy to use and has
all the information I needed on the articles.&lt;/p&gt;

&lt;p&gt;But the thing with news is that it can only be truly relevant if it’s localized,
and since I live in France, I needed to get news from a local newspaper.&lt;/p&gt;

&lt;p&gt;So I chose to get news from &lt;a href=&quot;http://www.lefigaro.fr/&quot;&gt;Le Figaro&lt;/a&gt;, which is
a French daily morning newspaper. Sadly, &lt;a href=&quot;http://www.lefigaro.fr/&quot;&gt;Le Figaro&lt;/a&gt;
does not provide any &lt;strong&gt;API&lt;/strong&gt;, but it has its own &lt;em&gt;rss feed&lt;/em&gt;
&lt;a href=&quot;http://www.lefigaro.fr/rss/figaro_actualites.xml&quot;&gt;here&lt;/a&gt;, and parsing &lt;em&gt;rss
feed&lt;/em&gt; is really easy with &lt;strong&gt;Python&lt;/strong&gt; using
&lt;a href=&quot;https://pythonhosted.org/feedparser/&quot;&gt;feedparser&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;weather&quot;&gt;Weather&lt;/h1&gt;

&lt;p&gt;While I was implementing the &lt;strong&gt;API&lt;/strong&gt; gatherers, I had another idea for
improvement. One thing I do every day is checking the weather in the morning,
so I chose to add a weather gatherer.&lt;/p&gt;

&lt;p&gt;The weather website I decided to use was the popular
&lt;a href=&quot;https://openweathermap.org/&quot;&gt;OpenWeatherMap&lt;/a&gt; which is well-known for providing
an easy-to-use and free weather API for over 200 000 cities.&lt;/p&gt;

&lt;p&gt;This allowed me to get the weather for the next 24 hours with a 3-hour interval
which was accurate enough for me.&lt;/p&gt;

&lt;h2 id=&quot;displaying-the-data&quot;&gt;Displaying the data&lt;/h2&gt;

&lt;p&gt;Once I had gathered everything I wanted, I had to decide how the results would
be brought to me and when.&lt;/p&gt;

&lt;p&gt;The when was an easy question, indeed, I designed most of the &lt;strong&gt;API&lt;/strong&gt; calls to
get information for today, so I decided that I wanted to get the results daily.&lt;/p&gt;

&lt;p&gt;But how was a trickier question…&lt;/p&gt;

&lt;h1 id=&quot;command-line-tool&quot;&gt;Command Line Tool&lt;/h1&gt;

&lt;p&gt;The easiest thing I could do was to simply do command line calls to my
&lt;strong&gt;Python&lt;/strong&gt; program and display the formatted output on my computer’s shell
every time I wanted to have this information.&lt;/p&gt;

&lt;p&gt;This is pretty easy, I simply had to write a few functions to format the data I
gathered from the different &lt;strong&gt;API&lt;/strong&gt;s and have an entry &lt;strong&gt;Python&lt;/strong&gt; file, which
once executed would make all the calls, format the output and display them to me.&lt;/p&gt;

&lt;p&gt;With a few tricks, I could have made this as a simple shell command I could
call from anywhere (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showNews&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The issue with this solution would be that I would have had to open my laptop
and start the program each time, this is something I do pretty often, but the
goal was to get the news every morning easily, and opening my laptop is not the
first thing I do every morning.&lt;/p&gt;

&lt;h1 id=&quot;website&quot;&gt;Website&lt;/h1&gt;

&lt;p&gt;The second solution I explored was to display the gathered data in a website,
so that I could read the news every morning on my phone, laptop or pretty
much anything with internet.&lt;/p&gt;

&lt;p&gt;Deploying small websites is something I have done a lot, so I already had the
technologies figured out, &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt; in the
back-end, classic &lt;strong&gt;HTML&lt;/strong&gt; and &lt;strong&gt;CSS&lt;/strong&gt; in front-end with
&lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Boostrap&lt;/a&gt; to have something fast and not too ugly.&lt;/p&gt;

&lt;p&gt;To deploy my website online, I would use &lt;a href=&quot;https://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; which
I really enjoyed since it allows me to deploy free websites and I find the git
deployment really easy and smooth.&lt;/p&gt;

&lt;p&gt;There were two issues (that I found) with the website solution.&lt;/p&gt;

&lt;p&gt;First, it was a lot more work than what I was going for in the beginning,
because creating and deploying a simple website is still a consequent amount
of work if I want to do it well.&lt;/p&gt;

&lt;p&gt;The second issue is that this program’s goal was to be as light and small as
possible but turning this repository into a Django website was going to make it
way heavier than I wanted. Of course, I could keep this repository to only
perform the API calls, and design the Django website in another repository, but
another goal I had was to have everything in the same repository, so that was
not going to work.&lt;/p&gt;

&lt;h1 id=&quot;emails&quot;&gt;Emails&lt;/h1&gt;

&lt;p&gt;The solution I chose to use was emails. This was pretty easy, I wrote a few
functions which formatted the gathered data to be easy to read in an email,
then I created a gmail account for this purpose, and using
&lt;a href=&quot;https://docs.python.org/3/library/smtplib.html&quot;&gt;smtplib&lt;/a&gt; I was able to
send an email to a target I chose.&lt;/p&gt;

&lt;p&gt;But what I wanted to do wasn’t to open my laptop every morning, run a
&lt;strong&gt;Python&lt;/strong&gt; program and then go to my email reader to read the email I just
sent myself, this would just be a waste of time and would be like the &lt;em&gt;command
line interface&lt;/em&gt; solution but more complicated.&lt;/p&gt;

&lt;p&gt;What I needed was for these emails to be sent programmatically every morning,
no matter if I had access to my laptop at that time.&lt;/p&gt;

&lt;p&gt;Another thing I wanted was to be able to send the email to multiple
targets, and to be able to update the target list &lt;em&gt;easily&lt;/em&gt; without having to
alter my code.&lt;/p&gt;

&lt;p&gt;So, I took a free &lt;a href=&quot;https://aws.amazon.com&quot;&gt;AWS&lt;/a&gt; &lt;strong&gt;EC2&lt;/strong&gt; which I could easily
access through &lt;em&gt;ssh&lt;/em&gt;. There, I cloned my repository, added my credentials and
added a local &lt;a href=&quot;https://www.postgresql.org/&quot;&gt;PostgreSQL&lt;/a&gt; database on which I
stored all the target emails.&lt;/p&gt;

&lt;p&gt;So, every time I’d call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender.py&lt;/code&gt;, the calls to the &lt;strong&gt;API&lt;/strong&gt;s would be made, the
results formatted and then an email would be sent to each target on the target
list.&lt;/p&gt;

&lt;p&gt;And last, to be sure my server would trigger the &lt;strong&gt;Python&lt;/strong&gt; package every
morning, I added a &lt;a href=&quot;https://en.wikipedia.org/wiki/Cron&quot;&gt;cron job&lt;/a&gt; for each
morning at 8 a.m., here’s the content of my crontab (opened with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crontab -e&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 8 * * * ~/cron/news.sh 2&amp;gt;~/log/error.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;news.sh&lt;/code&gt; is a simple bash program used to call my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender.py&lt;/code&gt; file, I used
it to make some tests and I’m pretty sure it isn’t required anymore, so I might
refactor this in the future.&lt;/p&gt;

&lt;h1 id=&quot;languages&quot;&gt;Languages&lt;/h1&gt;

&lt;p&gt;To speak briefly about the languages, since I was getting French articles from
&lt;a href=&quot;http://www.lefigaro.fr/&quot;&gt;Le Figaro&lt;/a&gt;, I was not able anymore to do a full
English software. So I decided to have two versions of the sent emails: English
and French, the English one using &lt;a href=&quot;https://www.theguardian.com/&quot;&gt;The Guardian&lt;/a&gt;
and the French one using &lt;a href=&quot;http://www.lefigaro.fr/&quot;&gt;Le Figaro&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Right now, the emails I send myself are in French, but the way I designed this,
it could be swapped by changing two characters in the code. In the future, I
might add the desired language in the database next to the target emails to
make this more flexible.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;Now, each morning I get an email looking like this:
&lt;img src=&quot;/assets/smlepnews_french.png&quot; alt=&quot;French example
email&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And this is how the English version would look:
&lt;img src=&quot;/assets/smlepnews_english.png&quot; alt=&quot;Example email&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The email design is pretty poor in my opinion, but it brings me the information
I need each morning so I don’t think I will try to spend hours to try to have
pretty emails since the email part is not the main purpose of this project.&lt;/p&gt;

&lt;p&gt;To conclude, I really enjoyed working on this project and writing this post,
so I will try to find another small project of this kind to work on soon and I
might be back with another post of this kind.&lt;/p&gt;

&lt;p&gt;Thanks for reading this!&lt;/p&gt;

&lt;p&gt;The source code for this project can be found
&lt;a href=&quot;https://github.com/Smlep/smlepNews&quot;&gt;here&lt;/a&gt;, you can leave a star if you find it
useful :blush:.&lt;/p&gt;

&lt;p&gt;Edit: I have implemented a website to subscribe to these daily news with custom
configurations, go check it out it’s free:
&lt;a href=&quot;https://www.mycustomnews.com/&quot;&gt;https://www.mycustomnews.com/&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html">Context</summary></entry><entry><title type="html">SpacingChecker: A huge tool to do one simple thing</title><link href="/jekyll/update/2018/10/31/spacingChecker.html" rel="alternate" type="text/html" title="SpacingChecker: A huge tool to do one simple thing" /><published>2018-10-31T00:00:00+00:00</published><updated>2018-10-31T00:00:00+00:00</updated><id>/jekyll/update/2018/10/31/spacingChecker</id><content type="html" xml:base="/jekyll/update/2018/10/31/spacingChecker.html">&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;

&lt;p&gt;I have written some posts about
&lt;a href=&quot;https://github.com/Smlep/SpacingChecker&quot;&gt;SpacingChecker&lt;/a&gt; in the past to talk
about how the project was changing and what I was adding, but now that I think
I am done with it, it’s time for a concluding post to talk about what really
was that project and why it existed.&lt;/p&gt;

&lt;p&gt;A few months ago, I started to have to this work in parallel with my studies,
where, among other things, we write tutorials for students to help them learn
how to code. We are a small team working on it, and one thing I have to do that
others don’t is reviewing what the people I work with write.&lt;/p&gt;

&lt;p&gt;So, when someone wants to add a new paragraph in a tutorial, he has to create
a &lt;strong&gt;Merge Request&lt;/strong&gt; on our GitLab and I (or the other guy who is also in charge
of reviewing) have to review and merge if everything is fine.&lt;/p&gt;

&lt;p&gt;Of course, everyone did spelling mistakes since we were all only getting
started with this job, but there was one kind of mistake that most people did
really often: adding, or not, spaces around punctuation. Should we put a space
before a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;? Is there a space after a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt;? What about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;, is this
the same rule?&lt;/p&gt;

&lt;p&gt;In the end, the answers to these questions were pretty simple, but the issue
is that it is language dependent, and more precisely, these rules were really
different between English and French.&lt;/p&gt;

&lt;p&gt;But we were French students, writing English tutorials, so there was a great
deal of confusion about what rule to use, and that meant many mistakes.&lt;/p&gt;

&lt;p&gt;I knew that eventually, these rules would stick and that nobody would make
these mistakes anymore, but it was going to take some time and I was getting
tired of leaving 20 comments on each &lt;strong&gt;Merge Request&lt;/strong&gt; so I decided to create a
tool to be able to check if someone made this kind of mistake.&lt;/p&gt;

&lt;h2 id=&quot;the-few-hours-long-project&quot;&gt;The few hours long project…&lt;/h2&gt;

&lt;p&gt;At this point, I wanted to create in &lt;strong&gt;a few hours&lt;/strong&gt; a light program to display
the spacing mistakes in a text, so I chose which technologies I would use
accordingly.&lt;/p&gt;

&lt;p&gt;I could have gone for Python to have a program which would parse a file and try
to find how spaces were set around punctuation, or maybe the same thing in C or
C++ which would be harder to create but would have way better performance. But
I didn’t care about the performance, It didn’t matter to me if checking a text
file would take 0.002 second or only 0.1 second so I did not go for C or C++.&lt;/p&gt;

&lt;p&gt;When I started to think about it, the easiest way to detect these errors would
be to parse my file with &lt;strong&gt;regular expressions&lt;/strong&gt; (which I’ll call &lt;strong&gt;regexs&lt;/strong&gt;),
so I decided to go for the simplest way I knew to match regular expressions in
file: &lt;a href=&quot;https://www.gnu.org/software/grep/&quot;&gt;grep&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.gnu.org/software/grep/&quot;&gt;grep&lt;/a&gt; is a command line tool which finds
lines matching a pattern in files, all I had to do was to create &lt;strong&gt;regexs&lt;/strong&gt;
which matched the spacing errors, feed them to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; with the files I wanted
to check, and that was it: a few hours work!&lt;/p&gt;

&lt;p&gt;So I started to implement this simple shell program, I decided to first write
the rules for French, knowing that I would do the same for English shortly
after.&lt;/p&gt;

&lt;p&gt;To have a flexible program, I chose to store the languages configurations in
different files, which I called language files and gave the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lg&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;My program was then divided into two files: the language file for French
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;french.lg&lt;/code&gt;) which looked like this back then:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ,
 \.
[^ ]?
[^ ]!
[^ ];
[^ ]:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the checker (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check.sh&lt;/code&gt;) which consisted in a loop going through my
language files to then call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; on the target file with each &lt;strong&gt;regex&lt;/strong&gt;
contained in the language file.&lt;/p&gt;

&lt;p&gt;A few minutes and commits later I had the English language file ready, the
French language file had been improved so I had reached what I wanted to
have in the beginning: a simple program to detect some spacing errors in a
text file in English or French.&lt;/p&gt;

&lt;p&gt;My repository at this point can be found
&lt;a href=&quot;https://github.com/Smlep/SpacingChecker/tree/4cd6cc179914720c0059dd7588f742f56cd4bdce&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But, by the time I had reached this point, I had  many new
ideas for this program. Most of them were pretty simple or useless, but I
wanted to improve my &lt;a href=&quot;https://github.com/Smlep/SpacingChecker&quot;&gt;SpacingChecker&lt;/a&gt;,
so I continued to work on this.&lt;/p&gt;

&lt;h2 id=&quot;turning-this-program-into-a-complete-and-useful-checker&quot;&gt;Turning this program into a complete and useful checker&lt;/h2&gt;

&lt;p&gt;The first thing I wanted was to have options, so that this program could be
used in many situations, at this point I already had a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt; option
but I decided to add a few more and to change how I implemented &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;help&quot;&gt;Help&lt;/h1&gt;

&lt;p&gt;Since I was beginning to have a big &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README&lt;/code&gt; file which described how my
program worked, I realized that the best solution for me would be to simply
display the content of my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README&lt;/code&gt; when someone would trigger the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt;
option. It seemed like a good solution back then, but now the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README&lt;/code&gt; has
gotten pretty huge, so I might need to rewrite a real help function in the
future.&lt;/p&gt;

&lt;h1 id=&quot;silent&quot;&gt;Silent&lt;/h1&gt;

&lt;p&gt;The silent option, triggered with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--silent&lt;/code&gt; would hide everything
which should be printed on the standard output, so that the only way to know if
the program found any errors would be to look at the exit code.&lt;/p&gt;

&lt;p&gt;I implemented that the simplest way I knew how (there might be a better
solution) is by redirecting the standard output in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting &lt;a href=&quot;https://github.com/Smlep/SpacingChecker/blob/master/check.sh#L135&quot;&gt;code&lt;/a&gt;
looks like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if [ $SILENT -ne 0 ]; then
  exec 1&amp;gt;/dev/null
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;languages&quot;&gt;Languages&lt;/h1&gt;

&lt;p&gt;At this point, I had changed the structure of the language files, it was not
only a list of regex anymore, but there also was a &lt;strong&gt;name&lt;/strong&gt; for each file and a
&lt;strong&gt;short name&lt;/strong&gt;, so each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lg&lt;/code&gt; file started like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Name: French
# Short: fr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And if we wanted to check a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.txt&lt;/code&gt; in French, we could call&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./check.sh fr test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This made the syntax lighter than when we had to give the language file path.&lt;/p&gt;

&lt;p&gt;To display the list of the short names for the available languages, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt;option was created.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--lg&lt;/code&gt; or  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--languages&lt;/code&gt; display every available languages and their
short names:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./check.sh -l

Short names for available languages:
fr: French
gb: English (GB)
de: German
it: Italian
us: English (US)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once I had the language file structure figured out, I added more language files
(right now, there are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;french&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gb_english&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;german&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;italian&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us_english&lt;/code&gt;), and kept improving the regular expressions for each languages.&lt;/p&gt;

&lt;p&gt;So, I added support for ellipses (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt;), time (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hh:mm&lt;/code&gt;) and decimal numbers
(is it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.14&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3,14&lt;/code&gt; in this language?). These new rules are the reason why
I had to split GB English and US English.&lt;/p&gt;

&lt;h2 id=&quot;deploying-the-checker&quot;&gt;Deploying the checker&lt;/h2&gt;

&lt;p&gt;After adding a few options and three more languages my checker was now way bigger
than what I expected to create in the beginning. My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check.sh&lt;/code&gt; which contained
the shell script I used to perform the checking just went from 13 lines to more
than 150.&lt;/p&gt;

&lt;p&gt;To feel like what I created would not be a 100% useless, I tried to make it
easy to use for anyone, because at this point, it might seem easy to use, but
it was annoying to install.&lt;/p&gt;

&lt;p&gt;To run the checker, you had to clone the
&lt;a href=&quot;https://github.com/Smlep/SpacingChecker&quot;&gt;repository&lt;/a&gt; and then call the checker
from within the repository. To make it easy to install I decided to add it to
a real package manager.&lt;/p&gt;

&lt;p&gt;The only package manager I was really using being
&lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, I wanted to do at least this one, and if it was
not too hard, then I would make it able to be installed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pacman&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I won’t explain all the different steps I went through to add SpacingChecker to
Homebrew, but it took me an amount of time and mistakes way too high.
This was the first program I tried to add to Homebrew (and probably the last one
:sweat_smile:) and it took me quite some time to make this work.&lt;/p&gt;

&lt;p&gt;But in the end, I reached something and now it can be installed this way:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ brew tap Smlep/SpacingChecker
$ brew install spacingChecker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, to use this from anywhere, just call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spaceCheck&lt;/code&gt; command and
everything works.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ spaceCheck us tests/theTortoiseAndTheHare.txt

Looking for a language file...
Searching files corresponding to us
Loading English (US)

Checking tests/theTortoiseAndTheHare.txt:

No error found in tests/theTortoiseAndTheHare.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding SpacingChecker to Homebrew really made me lose my motivation, so I
decided not to add it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pacman&lt;/code&gt; for now, but I might do it
in the future.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This project took me a few dozen of hours in the end instead of only being a 2
or 3 hour project like I expected in the beginning.&lt;/p&gt;

&lt;p&gt;On the one hand, it may seem like a waste of my time since I spent all these
hours creating an almost-useless checker that will probably never be used by
anyone but me.&lt;/p&gt;

&lt;p&gt;But on the other hand, I learned how to build a complete tool from the
beginning to the “end” about a simple functionality and I feel like I learned a
lot about how to deploy something I created on Homebrew. Moreover, I feel like
a &lt;strong&gt;regex&lt;/strong&gt; beast now, so that’s good (but I’ll probably have forgotten
everything in a few months).&lt;/p&gt;

&lt;p&gt;So, maybe it was a waste of time, but I’m proud I worked on this anyway, and
honestly, &lt;strong&gt;I had time to waste&lt;/strong&gt; the weeks I worked on this.&lt;/p&gt;

&lt;p&gt;Since I really enjoyed working on that, I might come back with another
open-source project in a few weeks or months, as soon as I find an idea which
seems worthy of my time (but honestly, pretty much anything productive is I
guess).&lt;/p&gt;

&lt;p&gt;The source code for this project can be found
&lt;a href=&quot;https://github.com/Smlep/SpacingChecker&quot;&gt;here&lt;/a&gt;, you can
leave a star if you find it useful :blush:.&lt;/p&gt;</content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html">Context</summary></entry></feed>