blog projects contact

Single-table design in DynamoDB

_25_Sep_2024 database DynamoDB

Single-table design is a way to model your data so that all your entities and their relationships are in a single table in DynamoDB. This allows querying data in a single request and avoiding joins as they are not supported by DynamoDB, and has other cost and performance benefits.

To find an object in DB we need to query it using both its PK (partition key) and SK (sort key).
PK: "USER#123"
SK: "USER#123"

We must specify a sort key, so here both keys have the same value. This is the case for simle entities only. The id of the user is prepended by the type of entity and a '#' to delimit them.

Now if we want to specify the relation that a user can have a house, we can do that in the same table like so:
PK: "USER#123"
SK: "HOUSE#456"

This enables us to find the house if we know both user id and house id. Also to find all houses owned by the user only using their id:
query conditions: PK = "USER#123" and SK beginsWith "HOUSE#"

We can expand the house entry to contain info on the state of the house:
PK: "USER#123"
SK: "HOUSE#IN_CONSTRUCTION#456"

This way we can query all houses of this user, or only those in a specific state.
query conditions: PK = "USER#123" and SK beginsWith "HOUSE#FINISHED#"
This stacking can be done multiple times to allow range queries on different attributes. A drawback here is that to get a house by user id and house id, we also need to know its state. This is why we need to know our access patterns before making the schema.

Another technique to allow flexibility of queries is adding more indexes. DynamoDB supports multiple GSIs (global secondary indexes) per table. For example:
GSI1 PK: "CITY#Sofia"
GSI1 SK: "HOUSE#456"

We can now query all houses in a city without knowing the user id. This copies the object and that takes up space, this is the case even if the data is duplicated. The fields that are copied are specified on index creation: only PK and SK, some or all fields.

GSI overloading is a trick to use more global secondary indexes than you have set up or more than the limit is. It's good pracitce to keep the GSIs to a minimum to save on storage and write costs. We can do this by using the same GSI with a different PK and SK for each entity.

To demonstrate this design process we can go through the steps as I did for SpeedCook. The entities are:

  • Users
  • Recipes
  • Unlocked recipes

And the properties and relations they have:

  • Recipes have details
  • Users have details
  • User has many unlocked recipes

The rough functionality we want is:

  • CRUD users and recipes
  • Unlock recipe for user
  • List unlocked recipes for user

Based on the above we need to come up with the access patterns for each entity:

  • User
    • Get user profile
  • Recipe
    • Get single recipe
    • Get all recipes that can be cooked: open + unlocked
    • Get all locked recipes in a dietary category when choosing what to unlock
  • Unlocked recipe
    • Unlock a locked recipe (unique, only once for a single user)
    • Get all unlocked recipes for user
  • Cooked meal
    • Complete a cooking of a recipe by a user, non-unique - a user can cook the same recipe multiple times
    • See history of completed meals

Now we have everything we need to specify our schema. For each access pattern we specify if it reads or writes or both, if the target is the main index or a global secondary one, what is the query and a note on how it will be used:

Access pattern operation target PK / SK Notes
User CRUD R/W main PK USER#user_id
SK USER#user_id
Unique entry
Get single recipe R/W main PK RECIPE#recipe_id
SK RECIPE#recipe_id
Unique entry; non-key attribs: name, category, accessLevel cookingTime, imageName, ingredients, spices instructions
Get unlocked recipe ids for user, order by time of unlocking R main PK USER#user_id
SK begins_with(UNLOCK_TIME#)
Get all recipes that can be cooked in one or more categories: unlocked for user + open R GSI1 PK ACCESS#access_type
SK CATEGORY#category_id#recipe_id
three steps:
  1. get unlocked recipe ids for user
  2. get batchItem recipes by the recipe ids
  3. get all open recipes
Get all locked (for user) recipes in a dietary category when choosing what to unlock R step 1:GSI1, step 2:main step 1: PK ACCESS#access_type
SK CATEGORY#category_id#recipe_id,
step 2:
PK USER#user_id
SK begins_with(UNLOCK_TIME#)
two steps:
1.get all locked (attainable) recipes
2. get all unlocked recipe ids for user and remove them from the list of locked ones
Unlock recipe for user W main PK USER#user_id
SK UNLOCK_TIME#unlock_time

References:

  • Dynobase. “DynamoDB single table design made easy.” Accessed 25 Sept, 2024. https://dynobase.dev/dynamodb-single-table-design-tool
  • AWS. “Data modelling foundations in DynamoDB.” Accessed 25 Sept, 2024. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/data-modeling-foundations.html
  • AWS. “Best practices for using sort keys to organize data in DynamoDB.” Accessed 25 Sept, 2024. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-sort-keys.html

Animating SVG with simple JS

_21_June_2020 animation website

A nice looking effect can be achieved by gradually drawing a SVG. You can do this for an icon or some text that is made out of paths.

SVG files are just XML so you can use a SVG editor to make the paths and open the file with a text editor. When copying the tags to your HTML you should check if the code is also valid HTML, maybe you need to close the tags or delete some attributes.

You can fit this to your needs by having it also draw backwards by reducing the length that is overwritten each tick on the strokeDasharray. You can have this run when the page opens or an element is hovered or a menu text/icon is rendered.

Learning foreign language vocabulary

_03_May_2020 german language learning

Learning words in a new language is best done when connecting the concept of something directly to the word in the new language - as opposed to mapping the new word to the one in your mother tongue which is in turn mapped to the concept.

To help you and me form the habit of directly mapping the new word to the concept, I will show an example with words that makes this approach a necessity: the pronouns in the German language. German has multiple uses for 'sie' and in English we say 'you' for many different cases, so this missmatch and repeatedly using the same word for different meanings is a good example.

So first let's imagine or visualise the concepts:

Imagine talking to a friend. You are about to tell him something.
Imagine talking to multiple people.
Imagine speaking to the king. Address him formally.
Imagine talking about a group of people who are not present in the conversation.
Imagine talking about a woman who is not present in the conversation.

Nominativ:
Example sentence Concept

Hast du das getan?

Habt ihr das getan?

Haben Sie das getan?

Haben sie das getan?

Hat sie das getan?


Akkusativ:
Example sentence Concept

Ich sehe dich.

Ich sehe euch.

Ich sehe Sie.

Ich sehe sie.

Ich sehe sie.


Dativ:
Example sentence Concept

Ich gebe dir etwas.

Ich gebe euch etwas.

Ich gebe Ihnen etwas.

Ich gebe ihnen etwas.

Ich gebe ihr etwas.

sources:
https://en.wikibooks.org/wiki/German/Grammar/Pronouns
https://german.stackexchange.com/a/48144

Icons made by Freepik from www.flaticon.com

Informaton science fathers

_10_October_2019 history science

In the time of high attention to AI and data science we talk about the high value of data and how large amounts of it are precious. Governments try to regulate how it is collected, shared and protected. But do you know who are the fathers of information science?

I stumbled upon this wikipedia article of a Belgian who lived in the 19th and 20th centuries. The article had only 1400 visitors over the last 30 days. I thought it was a pity that I had never heard of that man. His name was Paul Otlet and he wanted access to knowledge for people. His friend and colleague Henry La Fontaine was the first president of the International Peace Bureau - the world’s oldest international peace organisation, with 10 of its members having receved a Nobel Peace prize - his article even less visited.

In short Otlet got fascinated by sharing information and setup a service where cards containing text were carefully curated and systematically queried. The amount of requests quickly grew in a matter of years. This is why I mentioned wikipedia earlier - it was the same idea - just in 1896, and much slower. It was meant to be easy to use for searching information and used a concept similar to hyperlinks.

The government of Belgium gave him buildings and budget to expand his efforts. But then the Great war started, where one of his sons lost his life. Otlet believed that forming an international organisation that promotes knowledge sharing can prevent future wars and he defined a charter of human rights.

I felt strange that the information about this man is not more well known. And it makes me think not about the man, but about the relationship we as a civilisation have with information. Its value over the centuries and our desire to ask for it and use it.

Another thing I found interesting is that he was not stuck in his ways and beliefs. When new tech like radio and microfilm came up he started incorporating it in his efforts. I can imagine how someone else would have seen these new changes as a threat.

He did also have dreams of building a utopian city that would be the center of the knowledge of the world, but despite never being even started he still worked on what he believed for the rest of his life.

References:

  • Britannica. "Paul Otlet". Accessed 22 Feb, 2025. https://www.britannica.com/biography/Paul-Otlet

Keyboard - detecting keys

_19_June_2019 arduino ghosting

Because we don't have enough inputs on the arduio we can implement a key matrix to detect which keys are pressed. This way the needed input are the number of columns plus rows.

The way it works is that we send a signal on one row and check which columns receive it. Then check the next row the same way.

The basic idea of the matrix scanning:

There is the problem called ghosting - keys which are not really pressed register as being pressed. Using diodes we can prevent the effect.

Here is how it happens when diodes are not present:

As you can see the right column does receive a signal when it is the top row's turn to send it, because the signal goes through the top-left pressed key to the left column and then to the bottom column through the bottom-left key and then to the bottom row through the bottom-right key. That means that the top right switch is registered as pressed, but it's not.

And here is the same scenario, but with diodes:

It is a good idea to test by soldering using very little tin - just enough to hold on, instead of trying to fiddle with holding them in place.

I decided to switch the wiring from the blogs I read - my rows are connected directly and columns use diodes

You can use this jewelry making pliers to make little loops that can go onto the switch legs or the wires.

The next problem to solve is debouncing - detecting that a key is pressed and realeased many times in a short time, while in fact the key is only being pressed or released, but the contact between the metal plates in the switch is not really solid while in the process of moving. After doing the research I found there are hardware and software ways to solve this problem. The hardware one is with capacitors, but that makes it more of a hassle for me. There are multiple ways to solve it with software:

  • waiting for a certain amount of time over which no change happens - this way we can be sure that the state is stable and we can read this as the current situation - this is slower, but might not be noticable
  • detecting the first change and registering that one, then ignoring changes for some time and checking the state after this time - this is per key and is making the decision faster than the previous one
  • only checking for changes every 50 milliseconds, for example - this is fast and easy to do, but is on all keys
  • track the state over time and accumulate the values to calculate to which extreme it is more close - this is not fast and might not be very robust without tuning

My first approach is to do it the simple way and put more effort when those results become unsatisfactory for my needs. So I will only check the state of all keys every 25 milliseconds.

The next thing to do is make a layout for our keys. I decided to have preprocessor macros that map a readable name to a keycode of type byte. I can send these bytes to the receiving host without mapping them. The key names I can use to initialize a 2D array which will represent how I want my keys to be ordered. When I know the position of a pressed key in terms of row and column I can then access the resulting keycode through the array.

Later on this could become a 3D array when we need to have multiple layouts.

Keyboard - figuring it out

_10_June_2019 DIY practical 3D print

A colleague of mine has a fancy keyboard - the OKLB Planck. It is sold as a DIY kit that you assemble and program yourself. I was unsure how I feel about it when I first saw it. But his explanations quickly got me fascinated and I decided to make my own - even more DIY style. I would 3D print everything and make some improvements like bluetooth. Another problem he had with his was the lack of a way to indicate on which layout level you are. And maybe a gesture sensor to swipe with. And maybe a gyroscope to use it like a mouse or driving wheel.

First I decided to go simple and just make a keyboard without bluetooth or anything fancy. Then learn from the mistakes and improve to make a second one that is closer to the real goal.

I ordered cheap switches and a pcb to make the process easier. At this point I thought that a big step of this project will be coming up with a good layout for my needs. Also because I take key bindings too seriously.

I found 3D models from the original designer and decided to print them. I also found a model of a keycap and modified it to make it printable without much support and add a bump for the index fingers. The keycaps turned out not fitting the switches, so I had to rework them a few more times.

The 3D models can be found here on my github.

The pcb was not fitting the models I found and was not very happy with them anyway, and they were not designed to be 3D printed to start with. I started planning how could I make a case that does not use bolts and nuts.

I printed a few simple clips see if I could use those. Some of them I printed impoperly, some were very stiff and I struggled to design better ones. I realised something very important then: instead of going for a perfect solution I should have gone for a satisfactory one and improve when needed.

I immediately made a few simple holes in a new top half model and found some M3 and M2 12mm bolts. After that I started designing a new bottom case, but adjusting it's height would have to wait.

Another problem was that I damaged or bricked the PCB so I also had to start again with that. The big problem was that I had soldered the switches onto the PCB, so I had to unsolder them one by one. It cost me 4 hours and a few burns to do that. But I did learn to do less ambitious planning upfront. I will never forget this lesson because fixing broken switches is one of the most tedious and fiddly things I’ve ever done.

The next step was to figure out how to use an Arduino for the keyboard I could flash it with the QMK firmware. Or write some code myself.

When you want to detect button presses on 48 keys while having less than 48 pins is not straight forward. So I found a few excellent blogs on how matrix scanning works:

  • http://pcbheaven.com/wikipages/How_Key_Matrices_Works/
  • http://blog.komar.be/how-to-make-a-keyboard-the-matrix/

After understanding the hardware I did some searching. First I found the matrix scanning code in a file from the Keypad library for Arduino. Then I found a file from a stenography keyboard open source project, which also did a similar job. It was very helpful to learn from this available code.

Making a keyboard without a pcb is called handwiring and I found a nice post about it: https://geekhack.org/index.php?topic=87689.0.

With the plan changed, and my student budget limits, I actually had more fun finding my way through.

DnD murder mystery inspiration

_02_May_2019 DnD session planning

I wanted to make a murder mystery for my DnD group. When the moment came and I started preparing for the session I found there is a lot of advice, but not a lot of easy inspiration. There are a few prepared adventures, and those are not very polished or detailed. I used some of them for inspiration and a base and stole some ideas from them. Maybe you can take mine and improve it to have fun with your players.

I had planned his for along time as I expected that one of my players would not attend at some point. Perfect opportunity to throw the characters into a pocket dimension for a one shot without advancing the main story. I gave one of them this book with empty pages and a whirlpool on the cover.

Make sure to have prepared statblocks for all the stuff they can encounter.

I was greatly inspired by the adventure called "How not to host a murder mystery"

I have not used names as I think it's easier to navigate the story with roles since we are looking at its structure and not for entertainment.

Everything starts in a whirlpool in the sea, hence the cover of the book. The characters are on a small ship with Victim heading to the city on the coast. During the whirlpool another group of adventurers (goblins?), who read another book of the same type, are summoned on the ship. Victim, Innocent and his colleagues are on the ship, and the characters are offered to to stay in the Victim's mansion. They were all summoned because he found this book and wanted to figure it out so cast some spells and activated all the books. Victim introduces Innocent as his brave but foolish, quick to act apprentice.

The mansion, Victim explains was built thanks to his father's successful business of trading rapiers, short swords and daggers. His father died 6 years ago.

Garden:
Morning glory - a flower that blooms in the morning because of sunlight and it's petals are closed when in shadow or darkness; a letter is hidden under the open petals in the day, but when darkness makes them close it is easy to spot. The letter is written with the same handwriting as the book of the Killer, it is to the girl of the apprentice saying that he will not give up on their love. This can be used to have the Killer try to frame Innocent.

Time before dinner: the players are invited to do something before it is time for dinner:

  • With Killer and Innocent to practice spells [openly said] (so all 3 including the PC seem suspicious); Killer doesn't want to waste mana; The Innocent calls Killer by his middle-name. The other players will not know whom this name belongs when they see it.
  • With sister to show you around: offers a reward a knife from the father's collection of rare craftsman knives [openly said] (so the sister and the PC sound suspicious) In private they find that one specific knife is missing from its stand - Lord Kelnor's pearl dagger
  • With cook to help prepare the big dinner. [openly said]; In private he tells the motive of both Innocent and Sister. He is grumpy and very skilled with cutting meat with his knife; he says the sister has a necklace with a gem that allows her to seduce and control weak men

The players are given the information separately through notes and they should get a bit confused and suspect each other.

Dining room:
During dinner the characters can talk to Innocent, Killer, Victim's sister who is a paid assassin, the cook, the old nanny

Killer says he will go and help the cook to set up the table. Innocent says that he will go and find the host Victim because he should have been here already. He leaves the room and in a bit everyone hears him scream.

Victim is stabbed in the heart in his study. There is no weapon there. Actually the knife Killer used was conjured by Spiritual weapon.

Killer points the finger at innocent and explains his motive. Innocent explains that he had the choice to give up on his study, but made up his mind and was no longer interested in marrying the girl. Innocent has a fresh letter to her stating that he will find a way to be with her and won't give up on their love.

The real killer has to be found before sunrise otherwise the framed Innocent will be hanged.

Innocent is a young novice, brave but foolish, quick to act. Victim doesn't let Innocent marry the daughter of a blacksmith because she will distract him from his studies.

Cook - not speaking a lot / low voice / bitter

The study:
Has a book with spells (belongs to:Killer's name on the inside cover), every page has notes in the margins. Some of the notes are crossed out and with another color and handwriting more notes are taken. The second notes match the handwriting on the papers on Victim's desk. On the spell Spiritual weapon there are a lot of scribbles and in all caps: HAVE TO ASK <Killer's middle name> HOW TO CAST THIS!

Trophies on a shelf saying: First place in spellcasting/conjuring/arcana competition - Victim

Building the structure of the mystery:

  • Innocent has motive and opportunity(to go bring victim), but no means
  • Killer has motive(fame,praise), means(stabbing), opportunity(the fact that the apprentice and the sister now have a motive)
  • Cook has means(knife with blood), no motive and no opportunity
  • Sister has motive(she is younger and can inherit the mansion that she likes very much if her brother dies), but no means and no opportunity, but definitely suspicious being an assassin
  • Old nanny - no motive, no means, no opportunity

Switching to and customizing IntelliJ

_18_October_2016 IntelliJ comfort

Hello! Read on if you decided to switch to IntelliJ, set it up, make it comfortable and learn how to be more productive with it. This post covers some settings and custom shortcuts.

The first things that annoyed me were the popups in the top-right corner. To disable some of them: 'Event log' on the bottom-right (or Speech bubble icon) -> Settings. Disabling the balloons doesn't hide the notifications from the event log, so you can check that if you need to.

Next up is removing the default comment generated at the top of a new class file.
File -> Settings -> Editor -> File and Code Templates -> 'Includes' tab -> File header -> the comment is on the right -> delete it. If you would like to use this feature make sure to print the date in a less ambiguous format.

Another one is the vertical line in the editor that is set to 120 chars per line by default. To change the line limit:
File -> Settings -> Editor -> Code Style -> Right margin columns.
The Google Java Style Guide recommends a column limit of 100 chars.

Ok hotkeys. Some are very hard to reach, hard to learn or conflict with something else. Here are some recommendations how to make your life easier. You don't need to remove the old shortcut, so if someone else wants to use your Idea they can still use the default keys they know. Go to
File -> Settings -> Keymap
and find the ones you need to change, then click on them and select 'Add keyboard shortcut'. All of the recommended ones are unused and should be added as alternatives. For each entry I have specified: the name of the command, the default shortcut, the suggested one and an explanation.

Rename: default - Shift F6, suggested - Alt R. This default key is famous for being so hard to reach. Usage of rename should be encouraged as naming things is one of the hardest tasks in programming. Remember it as R stands for rename.

Find usage: default - Alt F7, suggested - rightAlt U. Shows you where a method/variable is used. One hand - easy. Associate U with usage.

Surround with...: default - Ctrl Alt T, suggested - Alt T. Surrounds the selected code with if/elseif/while/for/try... etc. Some Linux distros have the terminal shortcut bound to Ctrl Alt T so that causes a conflict. Even if you don't care about that the alternative is still 1 less key to press.

Delete line at caret: default - Ctrl Y, suggested - Alt X. In Eclipse it was easy to Ctrl D with one hand, but Ctrl Y requires both hands. The Alt and X keys are next to each other and this one is very easy to press. The X can be associated with double-crossing something.

Run: default - Alt Shift F10, suggested - Alt P. Usefulness depends on how often you run the project. P as in play for the green arrow icon. An even easier variant is Alt E as in execute.

Next, I have compiled a list of the more notable shortcuts. Some are based on people's opinion from Stackoverflow. A more complete list can be found here and here and you can always check the key for actions by pressing Ctrl Alt A in Idea.

Go to declaration => Ctrl B

Open class => Ctrl N

Rename refactor => Alt R; Shift F6

Refactor variable from expression => Ctrl Alt V

Extract method => Ctrl Alt M

Smart completion => Ctrl Shift Space

Cyclic expand word => Alt forwardslash

Complete statement => Ctrl Shift Enter

Reformat, Checkstyle, fix imports => Ctrl Alt L

Find in whole project => Ctrl Shift F

Switch tabs => Ctrl Tab

Quick fix/intentions => Alt Enter

Smart template => iter/psf/thr Tab

Find Usage => rightAlt U; Alt F7

Brief info => Ctrl mouseover

Duplicate => Ctrl D

New line below => Shift Enter

New line above => Ctrl Alt Enter

Expanding select => Ctrl W

Delete to word start => Ctrl Backspace

Delete line => Alt X; Ctrl Y

Paste previous copies => Ctrl Shift V

JavaDoc => Ctrl Q

Run => Alt P; Alt Shift F10

Go to previous/next method => Alt Up/Down

Go back to code => Ctrl Alt Left

Go to next error => F2

Expand all folded => Ctrl Shift =

Parameter info in method call => Ctrl P

Show TODO list => Alt 6

Bring up the file/class/method quicksearch => Shift Shift

Open the switcher => Ctrl Tab

Hide active window => Shift Escape

If you think a shortcut or setting you often use is missing - tell me!

The mystery of termite communication

_06_November_2015 artificial life emergent behaviour

Until the 1960s scientists could not explain how termites manage to organise their activity to gather and pile up in one place all the wood pieces they find. Different theories tried to explain this like unaudible languages, but the truth was that they just followed simple rules, from which emerged a complex behaviour.

By taking a piece of wood when they encounter it and dropping it when they encounter another one the termites move the pieces to one or more piles, which in turn also get combined into bigger piles. The result is cleared areas and compact piles.

My implementation of the simulation: on github


Balcony garden watering and monitoring

_April_2024 electronics garden

Some of my friends have a garden on their balcony. And I wanted one too, but was worried about watering it when I'm on vacation. Also wouldn't it be nice if it could work outside the house?

My requirements were:

  • Water the plants when they need it
  • Work without a power cable
  • Allow monitoring online

Here's how I solved them:

Measure soil moisture with sensors.

  • Use capacitive moisture sensors as opposed to the ones that have metal probes - they erode by electrolysis carrying molecules from one probe to the other. This contaminates the soil and affects precision.
  • Use multiple sensors in different parts of the pot.
  • Take multiple probes over a short time and average them to smooth out anomalies and improve precision.
  • Calibrate a threshold below which I would water.

Pump water from a 10L container.

  • Place a 5V water pump at the bottom of the tank.
  • Buy a watering hose and drippers (10 drippers over 2 long pots).
  • Place tank near and at the same height as the plants

Use a solar panel to charge a battery to power the system.

  • Deep sleep the device for half an hour to perserve energy.
  • Wake it up for 10-15 seconds to water, measure and post data. It spends most of its time sleeping.
  • A small solar panel supplying 600mA at 5V charges the 650mAh (~3.7V) LiPo battery multiple times over the sunny part of the day.
  • Use a esp32 chip instead of a whole board as the board's USB chip draws power even if the MCU sleeps. This dropped the power consumption tremendously during deep sleep: from 25mA to 350uA - less than 2% of the original.

Design a PCB for the esp32 chip.

  • Regulate power from the battery to 3.3V to power the chip.
  • Use a MOSFET to allow powering the pump directly from the battery.
  • Break out pins to connect solar panel, pump, battery, sensors and additional sensors in the future.
  • Allow PCB to be used with Arduino Mini for other projects.

Connect to the wifi and post a message that will save data in a DB.

  1. Use the esp32 chip to connect to my wifi.
  2. Post a message with all the data using MQTT to AWS IoT.
  3. Process the message using a rule to store the data in DynamoDB.

Put together a simple website to show data on a timeline.

  1. When the website loads it makes a request to the API gateway that will call a Python lambda.
  2. The lambda queries all recent events from DB and formats them in json.
  3. Use a JS library to draw the graph/timeline.

Digaram of components:

Blueprint of the PCB:


Download PCB files

Improvements for next year:

  • measure water level in tank
  • make more devices and tanks and refactor website to show their data
  • add a camera to take pictures of the plants by posting them to S3 through a lambda

Portable laptop cooling stand

_September_2021 DIY maker culture

Easy to fold and carry - 21mm thick, smaller than a 15" laptop, less than 600 grams.

On rechargeable batteries - not to drain the laptop battery, lasts 8 hours.

Elevates laptop screen at eye level for a healthy posture.

svg model

sharpshooter

_April_2021 keyboard only terminal

Minimal file manager in the terminal.

Single-key hotkeys for an easy workflow.

Simple to configure and hack at.

Find it on github

Keyboard

_June_2019 DIY maker culture arduino

A comfortable personalised keyboard.

Custom 3D models, simple understandable arduino firmware code, manageable wiring.

3D models and code

Der Robot3r

_December_2018 raspberry pi servos

A wooden robot that is an arm on tank tracks. The tracks were 3D printed and the wooden structure is made from glued sticks. A raspberry controls with Python the 4 servos of the arm and the 2 motors for the tracks.

Global epidemic simulation

_February_2017_-_July_2017 modelling

A simulation which allows you to design a disease and different medicine and apply both on the world. For each country there is information about its: healthcare system, population density, climates, transportation, connectedness. There are airplanes, boats and land transportation between countries. You can zoom and pan on the vector map and inspect each country and its current state.

Made together with:
Kaloyan Ivanov, Yasen Georgiev, Ivan Stoilchev

Find it on github

Virtual Evil

_November_2015_-_June_2016 cyberpunk LibGDX computer art

A cyberspace game made using LibGDX and Java 8. Fight against the AI overlord of a system gone rogue, navigate your way in barren artificial landscapes and try to comprehend where reality bleeds into virtuality. Made together with Bozhidar Hrusanov.

Download: from github

Invade yer space

_March_-_May_2015 UX Java

Java 2D space invaders game, but with a story twist. Captain Manol, a pirate captain, had his ship fleet sunken after a confrontation with the invading aliens, but managed to get hold of one of their ships. Now his mastery of sailing leads him on a revenge to invade the aliens' space.

I wanted to experiment with user experience: animations, notifications and sounds.

Download: from github

Sanity's Eclipse

_March_2015 opponent AI asteroids

A Java 2D asteroids game with spaceships based on rotating around and having to manage your velocity and acceleration. It has 5 different enemies which use different attack strategies, various powerups, fast dangerous asteroids. Made together with Bozhidar Hrusanov.

Find it at github

Haiduti

_December_2015 casual DnD pen and paper historical games

A tabletop historical role-playing game. The pdfs can be printed on paper and cut into cards. The story takes place in the late 1860s in the land of the Bulgarian people. The game mechanics are like a soft casual DnD one shot. There are many historically accurate weapons, fun facts and small doses of history, different places, characters, abilities for the players to choose, riddles and mysteries, action and combat, calm sceneries of nature's beauty.

Tepeliya pistol

Not just a weapon, but also a jewel, this pistol is lavishly decorated and engraved with delicate motifs. Occasionally a malfunction causes an explosion that can hurt the shooter's hand.

Ottoman knife

The ancient Persian blacksmiths knew the secret of the Damascus steel. Their blades had the ultimate qualities: flexible, but also very durable and sharp. A weapon forged from the material is easily distingishable with its chaotic motifs. The metal, named after the capital of Syria, cannot be created nowadays - the secret method of manufacture was lost in the 19th century.

Lefaucheux double barrel pistol

Not just a double-barrel pistol. It has two hammers and triggers. It is invented by the french gunsmith Casimir Lefaucheux, who strongly influenced the development of guns and created the first pistol with breech-loading.

Pepperbox pistol

Four-barrel revolver. The idea for the mechanism became popular in the end of the 18th century in Belgium and England. At that time the barrels were rotated manually by the shooter. After the industrial revolution they were quite popular during the 1830s in America because they were cheap; the other revolvers were more complex and expensive to manufacture.

Prussian grenade

A major drawback of the grenades of the 18th century is that usually the enemy has time to throw them back.

Deringer

The word deringer is used to refer to a small personal firearm that is easy to conceal, usually carried for self-defence. Henry Deringer starts to manufacture the first ones in the 1830s. Abraham Lincoln was assassinated exactly with such a pistol in 1865.

Find it here

You are the Defender

_April_2014 mini games text-based

I wanted to make a fantasy game with a lot of freedom and especially less popular features or activities to do. Things like gambling, playing minigames, praying to different deities, eating and drinking, ordering said food and beverages, talking with npcs without the purpose of getting something for it. This combined with the lack of epicness of the setting made it feel more ordinary and calm.

Find it at github

Bubble Rebel

_April_2013 competition C++

A 2D game written in 2 days and a half in C++ for game programming competition. The theme of all games was "bubbles". In the game you compete with the evil bubble to collect more bathroom bubbles and become the biggest bubble.

Download: from github

Yani: Rise to power

_March_2013 Allegro animation

Help my classmate Yani collect all the cultural relics so he can finally face his greatest enemy.

Download: from github

VSMGB

_February_2013 Game maker

A 3D horror game with excessive jump scares. You navigate dark rooms, tunnels, halls and corridors.

Download: from github

Strength and steel

_June_2012 2D RPG rendering

2D tiled fantasy game written in C++ with Allegro 4. The game has an inventory system, abilities and cooldowns, multi-layer map and map editor, character stats, an enormous map that is visibly chunked, npcs to talk to. It taught me basics of OOP, rendering 2D graphics and using arrays of pointers.

Beyond the next dimension

_October_2010_-_February_2012 3D FPS

A 3D shooter. The sprites from Doom made it grim and gory, while the other ripped weapon images made it feel like a violent collage. The simple geometry of the levels and doors added a good bit of amateurism. Building this game allowed me to apply knowledge in trigonometry and stereometry. Made with GM7 and Blender after following a book tutorial.

  • 9 levels
  • 4 weapons
  • 6 enemy types
  • 2 bosses

One of my friends even made a trailer for it.

Download: from github

WoV: MoV

_October_2011 text-based

My first C++ game - a text-based fantasy RPG with many different enemies, combat scenarios and outcomes.

Dimension Traveller Pesho

_2009_-_2010 platformer bosses

A platformer with a many levels. The last released version is lost, but this one has most of the levels and all of the bugs. The goal was to have a variety of levels not fitting with each other and not constrained by story. Most bosses have unique mechanics and theme.

Download: from github



Email: veselin@vsslavchev.com

LinkedIn

Github