Wed 10 October 2018

Random VM Name

Something I found to be cute about the docker engine is it's feature to create a random name for your containers, when one is not specified.

I've had some good ones e.g:

objective_galileo
distracted_euclid

Occasionally I'd be spinning up the odd VM and have to provide some generic name like dev-sebastien. So instead I thought my own arbitrary name generation could save some time here.

Random names

The idea was to combine <adjective>-<pokemon> and use this as the VM parameter.

Thus defining the following in .create_name.sh

function gen_name()
{
    pokemon=(
        "pidgey"
        "pikachu"
        "cubone"
    )
    adjectives=(
        "hungry"
        "adorable"
        "jittery"
    )

    select_pokemon=${pokemon[$RANDOM % {#pokemon[@]}] }
    select_desc=${adjectives[$RANDOM % {#adjectives[@]}] }

    local result=sebastien-$select_desc-$select_pokemon
    echo "$result"
}

Call this in your .bash_aliases file.

source .create_name.sh

And every time you run gen_name in your command line, you'll get a new "vm" name.

I've coupled this with:

create_instance(){
    gcloud compute instances create $(gen_name);
}

Here are some of the names of my machines:

sebastien-livid-quagsire
sebastien-lonely-metapod
sebastien-gentle-rattata
S Williams-Wynn at 19:19 | Comments() |

Tue 09 October 2018

Foolscap List Ordering

Foolscap was my answer to losing all my notes and forgetting the exact file I saved it.

Was it on Desktop or next to the project?

Thus I decided to write an application that took care of the saving and finding of my notes.

Unordered Lists

One thing I have taken for granted is the ordering of my files in any file system. I only realised how important it was after unordered dictionaries in python allocated my notes random positions on the list.

The random ordering meant if I have note "M" in mind, it could appear anywhere on the list. So my eyes would track down n positions in the list to find "M". An O(n) operation for my eyes.

After growing tired (a whole day of O(n) eye operations), I wrote the rule to provide me the list in alphabetical order. This was great my brain automatically switched to doing a binary search for note "M". O(log n)

Ordered Lists

Now that finding note "M" was optimised for my eyes, my finger had to press the down key until my cursor was on the note of choice. This wasn't good enough, I was referring to note "M" several times a day and the other notes I'd reference once a month were adding computation time to my finger.

This is where I introduced two of the most powerful rules of Foolscap. Since I tracked the number of views, and time it was last viewed or modified I could implement the following ordering:

1: LastView/Modified/RecentlyCreated
2: MostViewed
3: 2ndMostViewed
4: 3rdMostViewed
5: A
6: Z

This was neat!

I had significantly cut down the amount of time it took for me to get to the notes I was using most frequently.

Search Lists

Searching needed a slightly different ordering since applying the rules above to your search results will likely be meaningless. The meaningless will come from your inability to predict what will appear in the list to begin with.

Python has a neat method for it's strings.

note_title.startswith("text")

Which I used as the initial search feature. A search by the prefix of my note title. To me this made sense since my notes are titled by their subject matter, e.g. "linux", "elastic".

The iteration to this search functionality was to include the conditional:

if "text" in note_title:

I still wanted to provide the user with the result of the initial prefix search as the first result in the list.

This is when I fathomed this solution:

search = [title for title, _ in notes.items()
          if query in title]

# Sort by the position the query appears in the title
return sorted(search, key=lambda title: title.index(query))

Pretty neat!

S Williams-Wynn at 22:37 | Comments() |

Tue 09 October 2018

Procedural Villages

My inspiration for any tool or project has always been the thought that it could be done better, either that or I'd feel like I would benefit a lot from a missing feature.

In my first embarked I attempted to create a dungeon crawler, full of all the creatures and characters I thought were missing from traditional games.

It was through brute-force of the Roguebasin tutorial where I learnt how to code.

I must have created the same game 4 or 5 times before I decided to scrap the libtcod library and create a game without an interface.

Armed with stdout and turn-based printing, I implemented feature after feature. One of the features I was quite proud of was the randomly generated villages I'd spawn my player into.

Objects

I was aiming for something simple, just populate the map with houses that the player can interact with, for this I deconstructed a house into a rectangle.

class Rect:
    def __init__(self, x, y, h, v):
        self.x1 = x
        self.y1 = y
        self.x2 = x + h
        self.y2 = y + v

    def center(self):
        center_x = (self.x1 + self.x2) / 2
        center_y = (self.y1 + self.y2) / 2
        return (center_x, center_y)

    def internal(self, x, y):
        """
        [ ][ ][ ][ ]
        [ ][X][X][ ]
        [ ][X][X][ ]
        [ ][X][X][ ]
        [ ][ ][ ][ ]
        """
        ...
        return bool()

    def edges(self, x, y):
        """
        [X][X][X][X]
        [X][ ][ ][X]
        [X][ ][ ][X]
        [X][ ][ ][X]
        [X][X][X][X]
        """
        ...
        return bool()

    def sides(self, x, y):
        """
        [ ][X][X][ ]
        [X][ ][ ][X]
        [X][ ][ ][X]
        [X][ ][ ][X]
        [ ][X][X][ ]
        """
        ...
        return bool()

The poorly defined object above could now provide boolean confirmation to a co-ordinates existence in appropriate sections of a rectangle.

From the above Rect class I can place a door on a Rect.sides() and I can fill the area defined by Rect.internal() with items.

Empty space: | . |
Wall:        | # |
Monster:     | m |
Door:        | + |

| . | . | . | . | . | . |
| . | # | # | + | # | . |
| . | # | m | . | # | . |
| . | # | . | . | # | . |
| . | # | . | . | # | . |
| . | # | # | # | # | . |
| . | . | . | . | . | . |

Throwing in some size variations and randomising the house position on the map, (making sure there are no houses intersecting each other). Allowed me to generate maps that looked like these:

Example 1

| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | # | # | # | # | # | # | . | # | # | # | # | . | . | . |
| . | # | u | . | . | @ | # | . | # | . | m | # | . | . | . |
| . | + | . | . | . | . | # | . | # | . | . | + | . | . | . |
| . | # | # | # | # | # | # | . | # | # | # | # | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | > | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | # | # | + | # | # | # | . | . | . | . | . | . | . | . |
| . | # | . | . | r | . | # | . | . | . | . | . | . | . | . |
| . | # | . | . | . | . | # | . | . | . | . | . | . | . | . |
| . | # | # | # | # | # | # | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |

Example 2

| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | # | # | + | # | . | . | . | . |
| . | . | . | . | . | . | . | # | . | . | # | . | . | . | . |
| . | . | . | . | . | . | . | # | . | . | # | . | . | . | . |
| . | . | . | . | . | . | . | # | m | . | # | . | . | . | . |
| . | . | . | . | . | . | . | # | # | # | # | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
| . | . | . | . | . | . | . | . | . | . | . | # | # | # | # |
| . | # | # | # | # | # | # | # | . | . | . | # | . | . | # |
| . | # | . | . | . | . | u | # | . | . | . | + | . | . | # |
| . | + | . | . | . | . | . | # | . | . | . | # | > | . | # |
| . | # | X | . | . | . | . | # | . | . | . | # | . | r | # |
| . | # | # | # | # | # | # | # | . | . | . | # | # | # | # |
| . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |

Unfortunately my code was not beautiful back then. I still think it was a neat idea

S Williams-Wynn at 21:48 | Comments() |
Socials
Friends
Subscribe