This is a portfolio of my software projects, presented in chronological order.
I provide comments on:
- What the project accomplishes
- When it was written
- How it functions
- And why it uses certain logic
Not all of my projects are discussed on this page. So stay tuned for more!
Jump to the project which interests you the most.
- Map Symbols
- Match the Ordnance Survey map symbol shown to the corresponding button
- Pip Calculator
- Estimate the time it will take complete divisions in World vs World
- Configuration files and scripts for Debian GNU/Linux systems
- This website! I hope you like it 😁
Try the demos from the browser.
|Map Symbols||Pip Calculator|
Map Symbols (2016)
The goal of the game is to match the Ordnance Survey map symbol shown to the corresponding button.
It is licensed using the Apache License 2.0.
Why not play from the browser and see for yourself?
|Play Map Symbols|
To win the game, the user must have five correct answers on the scoreboard.
The symbol shown must be pseudo-randomly generated
Math.Random()function is used to assign a number between
Num, which is used to select a symbol from
To avoid a symbol being repeated immediately, the value of
Numis assigned to
PreviousNum. If the values in both variables are equal,
RandNum()assigns a new number to
PreviousNumare no longer equal.
A star must be “turned on” when a correct answer is given
A new game begin with all five stars “turned off”. The game is won when they are all “turned on”.
Each button fires an
onClick()event to the
CheckAnswer()function, which passes the
The values of
- If they are equal, the answer is correct
- Else, the answer is incorrect
A corresponding sound and message should be used whenever an answer is given
Example of a correct answer:
Example of an incorrect answer:
The sound functionality was provided by the deprecated
<bgsound>element, but now uses the modern
<audio>element to emulate the same behaviour.
The respective module was taught by Mark Dixon and Liz Stuart, whose approach to teaching made learning to program a joy.
Guild Wars 2 Pip Calculator (2018)
For context, Guild Wars 2 is a Massively Multiplayer Online Roleplaying Game (MMORPG).
A reward system was introduced into the game, which awarded player “pips” at five minutes intervals. The more pips a player receives, the faster they chip away at the total number of pips required to complete a tier.
The calculator estimates how long it would take a player to receive the rewards given upon the completion of a tier.
I was motivated to develop the tool as:
I wanted to use the functionality, and be able to share it with my friends
It turns out that doing these calculations manually is boring. Who knew?
A similar tool had not yet been publicly announced
The project had its first commit in September 2018, though it was functional from an earlier date.
It is licensed using the Apache License 2.0.
Try it, directly in the browser.
Pip Calculator is functional, but not beautiful.
It is naively responsive, using the
viewport meta tag, and
max-width body property.
The user enters a number of pips, optionally selects a tier to stop at, and is presented with the results.
Input is sanitised:
isNumberKey(): The keys pressed must be between 0 and 9
isNumberAllowed(): The value must be between 3 and 19
To ensure hours and minutes are displayed with or without plurals as appropriate, the
getCaseSwitch() function is used to determine which strings should be used, using the values of
The total time given is not equal to the additive time of each tier.
Tiers are presented with floored hours and rounded minutes. However, the decimal values of each tier are retained when adding
Only after every tier is calculated does
totalTime have its hours floored and minutes rounded. This results in the total time being longer.
After playing Guild Wars 2 for thousands of hours, I have something to show for it professionally. Thanks again, ArenaNet!
dotfiles was the latest incarnation of my ‘configuration files and scripts for Debian GNU/Linux systems’.
It was designed to accompany a network install of Debian with all
tasksel items de-selected.
The project encompasses two years of development in 2020 and 2021, though prior incarnations were available in 2018 and 2019 respectively.
It is licensed using the GNU Public Licence version 3 only.
dotfiles was discontinued after I moved from Debian to openSUSE Tumbleweed.
dotfiles was a moving target throughout development, as I changed tools, improved my understanding of the operating system, best practices within it, et cetera.
I learned to use three types of branches for dotfiles: main, development, and <feature>.
Once a milestone had been met, and the files had been tested, a release would be tagged. The tag would then be pushed to main.
Add complete features (see below) and bug fixes as atomic commits, ensuring they are trivial to revert.
Features were merged into the development branch using the
In the past, I had experienced broken files after committing incomplete features to the development branch. This was problematic, as I lived on the development branch.
Adopting feature branches largely cured this error in judgement.
I endeavoured to make files easy to understand, portable across machines, and use programmatic logic.
As a case study, I will refer to this Polybar launch script from the ArchWiki.
The script performs a naive check to see if the
polybar process has been killed:
# Terminate already running bar instances killall -q polybar # Wait until the processes have been shut down while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
What does this script do, and how can it be improved?
- Perform a command to search for the string
polybaramongst processes running on the system
- Use a bash-specific variable to check that the process was launched by the current user
- If the command exits successfully (i.e. the process is still running), wait for one second before issuing the same command again
- When the command eventually fails, assume that this means the string was not found, and that
polybaris no longer running
if pgrep --euid "$(id --user --name)" --exact polybar then # Kill existing polybar processes killall --quiet polybar # Wait for the processes to die wait $! fi
- Improve readability by using GNU long options
- Check the user id by using a POSIX-compliant command
- Programmatically wait for the previous command to finish executing
wait built-in solves the problems present in the
do-while loop. The
if statement can be exited immediately, and there is no reliance on nebulous parsing of another program’s output.
There are many reasons not to parse human-readable output to a script, for example if
- Experiences API or ABI changes
- Is not installed on the system
- Has been modified by the distribution maintainer
dotfiles was integral to my learning process for GNU/Linux.
I’m grateful to every single person who collaborated on the documentation I scoured to make dotfiles better.
The project uses the Hugo static site generator (SSG).
Why choose Hugo?
Hugo was chosen for two reasons:
- To abstract the design process
- To simplify content creation
A content management system such as WordPress is feature-rich, but complex. To my mind WordPress focuses on the following:
- Providing a graphical user interface for the user and administrator
- Enabling third-party developers to create themes, extensions and frameworks
For my purposes, I only require a theme. The fewer dependencies and code complexity, the better.
It just so happens that Hugo is among the most popular static site generators, alongside Jekyll and their ilk. Ergo, the third-party support, documentation and user-led discussion is readily available.
Choosing a theme
Many Hugo themes attempt to extend Hugo’s humble aspirations as an SSG. Hence, a non-starter for my purposes.
I eventually stumbled onto Gokarna, a theme which is:
- Available in light and dark themes
Which suits my needs exactly. Most importantly, being a minimal theme, most “pure” Hugo documentation is applicable.
Thanks to Yash Mehrotra and Avijit Gupta for developing Gokarna.
Copyright Notices and Attribution
© 2021 NCSOFT Corporation. All rights reserved. NCSOFT, ArenaNet, the interlocking NC logo, Aion, Lineage II, Guild Wars, Guild Wars 2: Heart of Thorns, Guild Wars 2: Path of Fire, Blade & Soul, and all associated logos, designs, and composite marks are trademarks or registered trademarks of NCSOFT Corporation. All other trademarks are the property of their respective owners.
Iwan Gabovitch (qubodup)
Tux Flat is licensed under the GNU General Public License v2.0 or later.
Yash Mehrotra and Avijit Gupta
Gokarna is licensed under the GNU General Public License v3.0 only.