cancel
Application Name
Programming Language: C#
Database: mySQL
The Bank of Java application was my first attempt at developing a full-stack application. I
had developed other applications in the past, both during my free time and for school, but
this was the first application I developed that used a GUI, backend and database.
The idea for the application came from a Java application that I had developed for a school
project (also named Bank of Java). I kept the same feature set that was in the Java app
(deposit, withdraw, statements and change password) and added some more (management of users,
transferring money, first-time setup and an administrator account).
Ironically, the application is developed in C# and this was my first real go at developing an
application using a programming language that is not Java. Luckily, since C# and Java are very
similar, I did not find C# to be too difficult.
Developing this application made me realise that systems are made up of many different components
and that the smaller the component, the better, as it allows you to reuse the component as
many times as you’d like without needing to re-do the whole component just to make a couple of
small changes to it.
It also made me realise the amount of work that goes into making a graphical application since
every animation, button, label, and icon needs to be individually coded and it must also look
good no matter what the device.
Programming Language: C#
Database: SQLite
Personally, I am an advocate of the fact that our personal information should be private
and that no one has the right to access our data without our consent. Hence, I make use of
Signal messenger, which is a messaging application that allows for end-to-end encrypted messaging.
Signal messenger allows you to take a local backup of your messages (since if something happens
to one’s phone, one would lose all their messages since they are stored locally on one’s device).
These backups are also encrypted with a code which you are given once the backup is complete.
But, at one point while using the app, I came to the realisation that if the app were to no longer
exist, I would not be able to view the messages in my backup file.
Hence, after finding out how to decrypt the backup (using signalbackup-tools open_in_new by bepaald
and tribut over on GitHub), I was able to develop an application in C# that took the
database which holds all the messages in the backup and outputs them for the user to see,
including images and replies.
The decrypter tool outputs all images, stickers and database files in one folder. Hence, in conjunction
with this app, I also developed another application which aids the user in sorting all the data that comes
out of the decrypted backup file. It does this by looking at the database file and sorting the images and
stickers into folders according to the message thread they were sent in.
The following code is found within the companion app. Given the address of the user on the system along with where the images/stickers/etc…
of that user should go, the application grabs each attachment sent (found in the main.parts table) and queries the main.mms
table to check if the attachment was sent to the selected user. If so, the application searches the root directory to find the
attachment and to store it in the folder the user specified.
string stm = "SELECT \"mid\",\"unique_id\" from \"main\".\"part\"";
string recipients = "SELECT \"_id\", \"system_display_name\", \"phone\" from \"main\".\"recipient\" where UUID is not NULL";
List<Recipient> recs = new List<Recipient>();
while (rd.Read())
{
recs.Add(new Recipient() { DisplayName=rd.GetValue(1).ToString(), Phone=rd.GetValue(2).ToString(), ID=rd.GetInt32(0)});
}
rd.Close();
bool parsed = false;
do
{
do
{
Console.WriteLine("Choose a recipient from the following list:");
for (int i = 0; i < recs.Count; i++)
{
Console.WriteLine($"[{i}] {recs[i].DisplayName} - {recs[i].Phone}");
}
Console.WriteLine("Type -1 to stop.");
parsed = Int32.TryParse(Console.ReadLine(), out addressGET);
} while (!parsed);
if (addressGET != -1)
{
if (parsed)
{
Console.WriteLine($"Enter the folder where you want to place the images for {recs[addressGET].DisplayName}: ");
copyTo = "\\" + Console.ReadLine() + "\\";
}
cmd = new SQLiteCommand(stm, con);
rd = cmd.ExecuteReader();
string[] files = Directory.GetFiles(baseloc);
string UID;
int mid;
string temp;
FileInfo fi;
SQLiteCommand cmd2;
SQLiteDataReader rd2;
if (conn2.State != System.Data.ConnectionState.Open) conn2.Open();
string stm2;
while (rd.Read())
{
mid = rd.GetInt32(0);
UID = (string)rd.GetValue(1).ToString();
stm2 = $"SELECT \"_id\",\"address\" from \"main\".\"mms\" where address={recs[addressGET].ID} and _id={mid}";
cmd2 = new SQLiteCommand(stm2, conn2);
rd2 = cmd2.ExecuteReader();
while (rd2.Read())
{
var tempArray = files.Where(f => f.Contains(UID)).ToArray();
temp = tempArray.Length == 0?null :tempArray[0] ;
if(temp != null)
{
fi = new FileInfo(temp);
try
{
fi.MoveTo(baseloc + copyTo + fi.Name);
}
catch (FileNotFoundException) { }
Console.WriteLine("Moved Attachment: " + UID);
}
}
rd2.Close();
}
rd.Close();
Console.WriteLine("Finished!");
}
} while (addressGET != -1);
con.Close();
conn2.Close();
Programming Language: Python
As the name suggests, this is a song guessing game. Given a set of locally stored music, it will randomly pick 3 songs and
start to play one of them for a specific period of time. The player then has a set of tries to guess which song is playing
from the three.
The music machine was my attempt at developing a game in Python and, in contrast to most of the applications in my portfolio,
this application does not have a graphical UI, nor does it utilise a database. I had developed this game before I had even
started sixth form meaning that the only language I had exposure to at the time was Java. In fact, one of the main reasons
for this project was to experiment with the Python programming language.
This game was developed at a point when I was still very naïve to programming, and the source code reflected that. In fact,
three years after I had finished the game, while I was in my first year of my software development course, I decided to
revisit the project in order to apply the best practices and concepts that I had gained throughout those three years.
When the game was re-developed, I was able to see the effect and importance of modularisation since a program that was bound
to one giant Python file, with barely any methods and classes (and lots of repetition), was split into many smaller classes
and functions which allowed for code reuse and better understandability of code.
The idea of the game is simple in theory however, since the game uses the music files provided by the user it must include
some extra logic to account for all the issues that can arise with the selection of files. This includes ensuring that there
are at least 3 music files before starting the game (since the user has to choose the correct song from three options), that
music files are not removed from the file system during runtime (otherwise the game won’t be able to find them and play them)
and that the music file has the appropriate metadata (to get the song’s name and artist - otherwise the game allows the user
to enter it manually).
Markup Languages: HTML, CSS
Programing Language: JavaScript
After developing the School Management System, I decided to give plain old JavaScript a try to see
how it differs from a JavaScript framework, and it is here that I made another game, Tetris.
Although Tetris seems simple in theory, similar to the music game there is more to it than
meets the eye. For example, I needed to make sure that the tetromino does not keep on going
left or right if it meets a border or another tetromino, otherwise, it gets mangled. I also
needed to make sure the tetromino does not keep going down once it hits the end of the grid
or if it hits another tetromino. I also coded in ghost tetrominoes so that the player would
know where the actual tetromino would land. These ghost tetrominoes are coded to imitate the
x location of the actual tetromino but to go as far down the grid as possible.
Would you like to play a game of tetris? If so, click here!
The following code is used whenever a block needs to move one line
down. It checks if any part of the tetromino has reached the far bottom or if it has
reached another tetromino. It then hides the block and regenerates it in its new position
(when the same tetromino is going down one line) or generates a new tetromino (when the
previous tetromino can no longer keep on going down).
As can be seen, this method uses recursion. This is only done when the user wants to push
the tetromino all the way down using the space bar.
function pushBlockDownLogic(pushToBottom, doGameLogic){
startingPoint+=10
repeatLogic = true
generateBlock = true
for(gridNum of tetrisConfigurations[chosenTetrisBlock][tetrisBlockRotation]){
//checking if the block is at the end of the grid
if(gridNum+startingPoint>209) {
generateBlock = false
repeatLogic = false
break
}
//checking if the block is hitting another block
if(checkIfTetrisTouched(gridNum)) {
repeatLogic = false
break
}
}
if(!pushToBottom){
if(generateBlock){
removeBlock()
drawBlock()
if(doGameLogic) gameLogic()
}
else{
stopBlockAndGenerate()
}
}
else{
if(repeatLogic) pushBlockDownLogic(true)
else{
startingPoint-=10
removeBlock()
drawBlock(true)
stopBlockAndGenerate()
}
}
}
The following code is used whenever a new block needs to be generated.
It stops the function that pushes down the blocks at specific intervals and disables all
keybinds temporarily until the new block is generated. The function also checks if there
is a line of blocks.
Then, the function checks if the grid is able to take any more tetrominoes and if so, it
generates a new block, otherwise, the game ends.
function stopBlockAndGenerate(){
clearLineMusicPlayed = false
gameProgressAudio = new Audio(baseLocation + 'lock.mp3').play()
clearInterval(pushBlockDown)
document.removeEventListener('keydown', keyDownActions)
currentTetris = Array.from(document.querySelectorAll('.active'))
currentTetris.forEach(block => {
block.classList.remove('active')
})
noClearLine = true
for(let i=0; i<allGrids.length; i++){
if(!allGrids[i].classList.contains('tetris-block')){
noClearLine = false
}
if((i+1)%10 == 0 && noClearLine){
clearLine(i-9)
if(!clearLineMusicPlayed) gameProgressAudio = new Audio(baseLocation + 'line-clear.mp3').play()
clearLineMusicPlayed = true
noClearLine = true
}
else if ((i+1)%10 == 0){
noClearLine = true
}
}
if((startingPoint-10)<=9) {
gameOver()
}
else{
updateScore(10)
generateNewTetris()
for(gridNum of tetrisConfigurations[chosenTetrisBlock][tetrisBlockRotation]){
generateBlock = checkIfTetrisTouched(gridNum)
if(generateBlock) break
}
if(!generateBlock) gameLogic()
else{
gameOver()
}
}
}
If a line needs to be cleared, the score is increased and
given the index of the first box in the line, the function removes all classes
from the boxes in the line and removes them from the main container and from
he array that has a reference to all grid boxes.
Then, it creates a new line of boxes and adds them to the array and to the top of the actual grid.
function clearLine(lineStartNumber){
updateScore(50)
for(let j=lineStartNumber; j<lineStartNumber+10; j++){
allGrids[j].classList.remove(...extraClasses)
container.removeChild(allGrids[j])
}
allGrids.splice(lineStartNumber, 10)
for(let k=0; k<10; k++){
gridBox = document.createElement('div')
gridBox.classList.add('grid-box')
allGrids.splice(k+10, 0, gridBox)
container.insertBefore(gridBox, container.children[k+10])
}
}
Frontend
Markup Languages: HTML, CSS
JavaScript Framework: ReactJS, with ReduxJS to handle state data
Backend
JavaScript Framework: NodeJS, with ExpressJS for routing
Database: MongoDB
This was my first attempt at developing a full-stack web application. I was always
interested in web apps and had always wanted to develop one but I did not know
where to start. However, after a bit of research and experimentation, I set sail
on my first web app, the (mini) School Management System.
At first, it was a very simple ReactJS application which allowed the user to input
homework and it would be displayed on the page. Over time, I then started to add
more features like a database, login system, different types of users
(teacher/student/admin), administrative control and student groups. By the end of
it, I had developed a very good grasp of JavaScript, CSS and HTML which are the
three technologies that power most websites that exist.
As I was developing the application, I started to wonder how the web app keeps an authenticated
user logged in and how the backend knows who called the API and how it ensures that requests are
performed only by people with the necessary rights without having to authenticate themselves every
time. It was at this point that I discovered the idea of tokens and how they can be used to represent
an authenticated user.
Incorporating such a token in the frontend, to make sure that users do not gain access to restricted
pages, was the most challenging since it involved redirecting the user to different pages depending
on their access rights which, in turn, would re-run the token checking logic to ensure its valid for
the redirected page. Hence, if not properly handled, the logic would result in infinite reloads and
constant signouts.
Using MongoDB also made me realise that there are different ways a database
can be stored and queried other than SQL. Personally, I enjoyed using MongoDB as it allowed me to
see how to query data using something other than SQL and the mongoose API was very easy to use with NodeJS.
Frontend
Markup Languages: HTML, CSS
JavaScript Framework: Angular
Backend
JavaScript Framework: NodeJS, with ExpressJS for routing
Database: mySQL
After spending some time coding in ReactJS for the school management system, I decided to try out another JavaScript
framework, Angular. It is here that I created my second web app, the Event Ticketing System.
One major leap forward that I managed to achieve with this system was cryptography. All other programs that I had
developed until now stored passwords as plain text, which, I know, is extremely insecure. I had always been interested
in cryptography and had intended to implement it in the School Management system however, at the time, I still did not
understand what cryptography was exactly.
After dedicating some time to see how cryptography works, I managed to successfully store all user passwords securely
in the system’s database. All passwords are hashed using SHA256 and all passwords have a salt added to them before they
are hashed, rendering a rainbow table useless. Both the salt and hashed password are stored in the database and to log
in, the front end sends the username and password to the backend and the backend gets the user’s salt by performing a query
using their username, appends it to the password, hashes it and checks it against the hashed password in the database. If
the hashed values match, the user is authenticated.
Speaking of databases, this application was developed before I started university and after the first year of my software
development course, I redeveloped the mySQL database from the ground up for two reasons. First of which was to implement
organisations within the system and secondly, to shift most of the database operations from the API (NodeJS) to the database
itself.
Implementing organisations required a re-design of the database since this change also brought about the introduction of
events and ticketholders and users’ access rights were now also bound to a specific organisation. Due to this change,
all queries had to be re-designed anyway and thanks to the knowledge I acquired from my first databases unit, I implemented
better queries through stored procedures and triggers within the database itself.
This system also has an aspect of logging to it since it keeps track of a ticket’s progress including when and who created a
ticket, scanned a ticket, enabled/disabled a ticket and edited a ticket.
In this web app, I also managed to upload a file from the frontend to the backend. This is an Excel file that allows the user
to import a large number of tickets in one go, instead of having to add every ticketholder one by one.
Markup Languages: HTML, CSS
Programming Languages: JavaScript
The website that you are currently on was made from the ground up by me.
This is the first time I tried out a single-page website, where all
the information is found on one long page.
It is also the first website where I put a lot of effort to make sure
that it could be viewed properly on as many devices as possible
(including mobile devices), in contrast to the School Management
system app which was not optimised at all for mobile viewing.
The picture gallery visible in some of these application information
boxes makes heavy use of JavaScript due to the carousel at the bottom
that dynamically moves, the arrow key shortcuts (you can hit the left/right
arrow keys to move between the images) and also for the logic that allows
you to view an image by just clicking on it from the carousel, without
needed to go through the images sequentially for it.