Starbeamrainbowlabs

Stardust
Blog


Archive


Mailing List Articles Atom Feed Comments Atom Feed Twitter Reddit Facebook

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression conference conferences containerisation css dailyprogrammer data analysis debugging defining ai demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics guide hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs latex learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation outreach own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference release releases rendering research resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

TraceRoutePlus

Hello!

Today I have for you a traceroute tool that I have built. I made it mainly for educational purposes, since I wanted to test the code behind it ready for something slightly more complicated.

Here is an example:

C:\>tracerouteplus github.com
Traceroute Plus
---------------
By Starbeamrainbowlabs <https://starbeamrainbowlabs.com>

=== github.com ===
 1: xxx.xxx.xxx.xxx 1ms
 2: xxx.xxx.xxx.xxx 33ms
 3: xxx.xxx.xxx.xxx 36ms
 4: xxx.xxx.xxx.xxx 54ms
 5: 4.69.149.18     119ms
 6: 4.53.116.102    115ms
 7: 192.30.252.207  118ms
 8: 192.30.252.130   118ms
=== github.com end ===

You can download the latest version of the tool from my repository. Instructions can be found in the download section of the README.

The code is up on GitLab, and pull requests are welcome :)

Edit: Moved to GitLab from GitHub.

Learning Three.js four: Maze Birthday Card

A maze for a birthday card

Hooray for the fourth 3 dimensional experiment!

This one is a birthday card for someone I know and is also much more complex than the others I have done so far. I ported a maze generation algorithm that I originally wrote in Python 3 to Javascript (I also have ported it to Lua, keep a look out for a post about Lua soon!) and then set about rendering it in 3D.

The aim is to get to the centre of the maze, where some 3D(!) spinning text is waiting for you. The maze generation algorithm is not designed to have the goal in the centre of the maze, so you will find that there are multiple paths that you can take from the centre that lead to different parts of the maze. I will make a separate post about the maze generation algorithm I have written later.

The collision detection is tile based and rather complicated (for me, anyway). I am surprised that nobody has written a library for this sort of thing.....

You can play with it here: Learning Three.js four

Rob Miles' Tags for Red Nose Day

The tags that I bought

Hello again!

Rob Miles sold these unique 3D printed tags generated by a python program for red nose day for £1 each. I bought 4. If you had a tag that was identical to a picture that he showed on the board in his Lecture in Rhyme (which was great by the way), then you won either a Remote control Car or a Robot. Needless to say I didn't win, but I did have a great time :)

Atom Feed Optimisations (and bugfixes)

Hello again!

I have made a few tweaks to this blog's feed that I think that you might want to know about.

Firstly, I fixed the bug with the named html entities breaking the feed. Apparently XML doesn't like named html entities much. This has involved a number of tweaks to atom.gen.php - You will see that the script is now ~30kb(!) - this is due to the inclusion of a named html entity to numeric html entity conversion table. You will now also see (?) if an unknown named html entity couldn't be converted successful.

Secondly, I have improved the performance of the feed by only showing the last 15 posts in the feed. I didn't notice at first, but this has been slowing the server down for some time because it been adding every post I have made so far (62 for those of you who are counting) to the feed, every time someone requests it.

Hopefully these changes don't have any unintended side-effects, but if they do please let me know in the comments below.

Soundbox: A Super Simple Sound Library

A sound waveform.

I little while ago I wrote the first version of Soundbox. I forgot to post about it earlier, so I am posting about it now.

Soundbox is a tiny Javascript library I wrote after adding sound to another of my projects via Audio(). I found that you could only play a given sound once, unless you set the currentTime property to 0. I knew that I would forget this later so I wrote a library to do this for me.

The entire library is 1.04kb unminified, and a tiny 0.64kb(!) when minified.

I have uploaded the source to a github repository here: sbrl/soundbox. You can also find usage information there in the readme.

Here are the direct links to the latest master versions:

Coding Conundrums 3

Number three in a series of more than two. But probably less than a thousand.

I have finished my solutions to Rob Miles' Coding Conundrums. If you want to complete them yourself before looking at my solutions, take a look at the pdf.

My solutions share quite a few functions, perhaps I should look into writing a library for them.

3.1: Total Carp

People keep coming to me and bragging about the fish that they just caught. They tell me the make of the fish, "Carp" for example, and how much it weighed, 2000 grams for example.

I want a program into which I can type:

  • The name of each latest fish
  • The weight of each latest fish
  • When I enter a fish called "Finished" (fish pun alert) I want the program to print out:

  • The heaviest fish(name and weight)
  • The lightest fish(name and weight)
  • The total weight of all the fish that have been entered

My solution uses structs - do you remember these from semester 1?

using System;
using System.Collections.Generic;

public class Program
{
    public struct Fish
    {
        public string Name;
        public int Weight;

        public Fish(string inName, int inWeight)
        {
            Name = inName;
            Weight = inWeight;
        }

        public override string ToString()
        {
            return String.Format("{0} at {1}g", Name, Weight);
        }
    }

    public static List<Fish> FishList = new List<Fish>();

    public static int totalWeight;

    public static void Main(string[] args)
    {
        int i = 1;
        while(true)
        {
            string inFishName = ReadString(String.Format("Enter fish {0}'s name: ", i));

            if(inFishName.ToLower() == "finished")
                break;

            int inFishWeight = ReadNumber(String.Format("Enter fish {0}'s weight (in grams): ", i));

            FishList.Add(new Fish(inFishName, inFishWeight));

            Console.WriteLine("Fish added.");
        }

        /// calculate the statistics ///
        // variable declaration
        Fish heaviestFish = FishList[0];
        Fish lightestFish = FishList[0];

        foreach(Fish currentFish in FishList)
        {
            if (currentFish.Weight > heaviestFish.Weight)
                heaviestFish = currentFish;
            if (currentFish.Weight < lightestFish.Weight)
                lightestFish = currentFish;

            totalWeight += currentFish.Weight;
        }

        // Print out the statistics calculated above
        Console.WriteLine("Total weight: {0}", totalWeight);
        Console.WriteLine("Heaviest fish: {0}", heaviestFish.ToString());
        Console.WriteLine("Lightest fish: {0}", lightestFish.ToString());
    }

    /// <summary>
    /// Reads a string in from the user.
    /// </summary>
    /// <param name="prompt">The prompt to display</param>
    /// <param name="minlength">The minimum length of the input the user enters.</param>
    /// <returns>The string the user entered.</returns>
    public static string ReadString(string prompt, int minlength = 1)
    {
        while(true)
        {
            Console.Write(prompt);
            string line = Console.ReadLine();
            if(line.Length < minlength)
            {
                Console.WriteLine("Please enter something that is at least {0} characters.");
                continue;
            }

            return line;
        }
    }

    /// <summary>
    /// Reads a number from the user.
    /// </summary>
    /// <remarks>Depends on ReadString()</remarks>
    /// <param name="prompt">The prompt to display to the user.</param>
    /// <returns>The number that the user entered</returns>
    public static int ReadNumber(string prompt)
    {
        while(true)
        {
            string line = ReadString(prompt).Trim();
            try {
                return int.Parse(line);
            }
            catch
            {
                Console.WriteLine("Sorry, that was not a valid number.");
            }
        }
    }
}

(Pastebin, 32 bit binary)

3.2: Fish Popularity Contest

It occurs to me that it would be useful to add another feature to the fish program above. I'd like to know which is the most popular fish. That way I can buy shares in it. Or something. So I've added the following extra requirement:

  • The most popular fish (i.e. the fish that we have seen the most of)

Note that my keyboard skills are not very gud. And so if I type CArp rather than Carp I'd like the program to behave sensibly and count them both as the same make of fish.

The addition of another List to the loop at the end of the program and a few extra bits and pieces yields FishListPlus:

using System;
using System.Collections.Generic;

public class Program
{
    public struct Fish
    {
        public string Name;
        public int Weight;

        public Fish(string inName, int inWeight)
        {
            Name = inName;
            Weight = inWeight;
        }

        public override string ToString()
        {
            return String.Format("{0} at {1}g", Name, Weight);
        }
    }

    public static List<Fish> FishList = new List<Fish>();

    public static int totalWeight;

    public static void Main(string[] args)
    {
        int i = 1;
        while(true)
        {
            string inFishName = ReadString(String.Format("Enter fish {0}'s name: ", i));

            if(inFishName.ToLower() == "finished")
                break;

            int inFishWeight = ReadNumber(String.Format("Enter fish {0}'s weight (in grams): ", i));

            FishList.Add(new Fish(inFishName, inFishWeight));

            Console.WriteLine("Fish added.");
        }

        /// calculate the statistics ///
        // variable declaration
        Fish heaviestFish = FishList[0];
        Fish lightestFish = FishList[0];

        Dictionary<string, int> PopularFish = new Dictionary<string, int>();

        foreach(Fish currentFish in FishList)
        {
            if (currentFish.Weight > heaviestFish.Weight)
                heaviestFish = currentFish;
            if (currentFish.Weight < lightestFish.Weight)
                lightestFish = currentFish;

            totalWeight += currentFish.Weight;

            int CurrentFishCount;
            if(PopularFish.TryGetValue(currentFish.Name.ToLower(), out CurrentFishCount))
            {
                PopularFish[currentFish.Name.ToLower()]++;
            }
            else
            {
                PopularFish[currentFish.Name.ToLower()] = 1;
            }
        }

        // Print out the statistics calculated above
        Console.WriteLine(" ----------------------------- ");
        Console.WriteLine("| {0,-12} | {1,12} |", "Name", "Count");
        Console.WriteLine("|--------------|--------------|");
        foreach(KeyValuePair<string, int> FishCount in PopularFish)
        {
            Console.WriteLine("| {0,-12} | {1,12} |", FishCount.Key, FishCount.Value);
        }
        Console.WriteLine(" ----------------------------- ");

        Console.WriteLine("Total weight: {0}", totalWeight);
        Console.WriteLine("Heaviest fish: {0}", heaviestFish.ToString());
        Console.WriteLine("Lightest fish: {0}", lightestFish.ToString());
    }

    /// <summary>
    /// Reads a string in from the user.
    /// </summary>
    /// <param name="prompt">The prompt to display</param>
    /// <param name="minlength">The minimum length of the input the user enters.</param>
    /// <returns>The string the user entered.</returns>
    public static string ReadString(string prompt, int minlength = 1)
    {
        while(true)
        {
            Console.Write(prompt);
            string line = Console.ReadLine();
            if(line.Length < minlength)
            {
                Console.WriteLine("Please enter something that is at least {0} characters.");
                continue;
            }

            return line;
        }
    }

    /// <summary>
    /// Reads a number from the user.
    /// </summary>
    /// <remarks>Depends on ReadString()</remarks>
    /// <param name="prompt">The prompt to display to the user.</param>
    /// <returns>The number that the user entered</returns>
    public static int ReadNumber(string prompt)
    {
        while(true)
        {
            string line = ReadString(prompt).Trim();
            try {
                return int.Parse(line);
            }
            catch
            {
                Console.WriteLine("Sorry, that was not a valid number.");
            }
        }
    }
}

(Pastebin, 32 bit binary)

3.3: Ingredients Tracker

Talking of food, I want something to keep track of ingredients that I might have in my kitchen. My program will have two modes:

  1. The program will start in this mode. I can enter the name and amount of each ingredient. If I type in the name "Search" the program will go into mode 2 (see below).
  2. I can type the name of an ingredient and the program will tell me how much of that ingredient I have in stock. If I type in the name "Enter" the program will go into mode 1 (see above)

If you fancy getting clever, you can add a third command, "List", which will list out all the ingredients that have been entered.This is making me quite hungry.

I think I’ll go off for a pie while you work on these.

I decided to use a dictionary for this one, which holds the amount of each item as an int, with the name as the key. Since you can't have duplicate keys, I ask the user if they type in the same key more than once whether they do actually want to overwrite their previous entry.

using System;
using System.Collections.Generic;

public class Program
{
    public enum Mode
    {
        DataEntry,
        Search
    }

    public static Mode CurrentMode = Mode.DataEntry;

    static Dictionary<string, int> Stock = new Dictionary<string, int>();

    public static void Main()
    {
        Console.WriteLine("Kitechen Tracker v0.2");
        Console.WriteLine("---------------------");
        Console.WriteLine("Coding Conundrum 3.3, challenge set by Rob Miles, conquered by Starbeamrainbowlabs");
        Console.WriteLine("Enter the special name 'search' to switch to search mode");
        Console.WriteLine("Enter the special name 'enter' to switch back to data entry mode");
        Console.WriteLine("Enter the special name 'list' at any time to view the current stock");
        Console.WriteLine();
        while(true)
        {
            switch (CurrentMode)
            {
                case Mode.DataEntry:
                    string inName = ReadString("Enter the name of the next ingredient: ").Trim().ToLower();
                    switch(inName)
                    {
                        case "search":
                            Console.WriteLine("Switching to search mode.");
                            CurrentMode = Mode.Search;
                            continue;

                        case "list":
                            ListStock();
                            continue;

                        default:
                            int inAmount = ReadNumber("Enter the amount: ");
                            int currentAmount;
                            if(Stock.TryGetValue(inName, out currentAmount))
                            {
                                if(!Confirm(String.Format("There is already an entry for {0} (with an amount of {1}). Do you want to overwrite it? (y / n)", inName, currentAmount)))
                                {
                                    continue;
                                }
                            }
                            Console.WriteLine("{0} has been added to the list.", inName);
                            Stock[inName] = inAmount;
                            break;
                    }
                    break;

                case Mode.Search:
                    string searchString = ReadString("Enter ingredient name: ").Trim().ToLower();
                    switch(searchString)
                    {
                        case "enter":
                            Console.WriteLine("Switching to data entry mode");
                            CurrentMode = Mode.DataEntry;
                            continue;

                        case "list":
                            ListStock();
                            continue;

                        default:
                            int amountInStock;
                            if(Stock.TryGetValue(searchString, out amountInStock))
                            {
                                Console.WriteLine("Amount of {0}: {1}", searchString, amountInStock);
                            }
                            else
                            {
                                Console.WriteLine("There isn't anything called {0} in stock at the moment.", searchString);
                            }
                            break;
                    }
                    break;
            }
        }
    }

    public static void ListStock()
    {
        Console.WriteLine("Current Stock:");
        foreach(KeyValuePair<string, int> Ingredient in Stock)
        {
            Console.WriteLine("{0,-12}: {1}", Ingredient.Key, Ingredient.Value);
        }
    }

    /// <summary>
    /// Asks the user a simple yes / no question.
    /// </summary>
    /// <param name="prompt">The prompt to display</param>
    /// <returns>The user's choice as a boolean</returns>
    public static bool Confirm(string prompt)
    {
        Console.WriteLine(prompt);
        while(true)
        {
            ConsoleKeyInfo nextChar = Console.ReadKey(true);
            switch(nextChar.Key.ToString().ToLower())
            {
                case "y":
                    return true;
                case "n":
                    return false;
            }
        }
    }

    /// <summary>
    /// Reads a string in from the user.
    /// </summary>
    /// <param name="prompt">The prompt to display</param>
    /// <param name="minlength">The minimum length of the input the user enters.</param>
    /// <returns>The string the user entered.</returns>
    public static string ReadString(string prompt, int minlength = 1)
    {
        while (true)
        {
            Console.Write(prompt);
            string line = Console.ReadLine();
            if (line.Length < minlength)
            {
                Console.WriteLine("Please enter something that is at least {0} characters.");
                continue;
            }

            return line;
        }
    }

    /// <summary>
    /// Reads a number from the user.
    /// </summary>
    /// <remarks>Depends on ReadString()</remarks>
    /// <param name="prompt">The prompt to display to the user.</param>
    /// <returns>The number that the user entered</returns>
    public static int ReadNumber(string prompt)
    {
        while (true)
        {
            string line = ReadString(prompt).Trim();
            try
            {
                return int.Parse(line);
            }
            catch
            {
                Console.WriteLine("Sorry, that was not a valid number.");
            }
        }
    }
}

(Pastebin, 32 bit binary)

C Sharp Performance Tests: Squaring Numbers

The semester 2 coursework has begun, and this time there is a choice of either make a game to a specification, or produce a business related application to a specification. I have chosen the game.

To start off, I started writing a few mathematical functions that I would need when ewriting the game itself. I quickly found that one of things you do rather a lot is squaring numbers. In C♯ I have found 2 ways to square a number so far: a*a and Math.Pow(a, 2), where a is a number.

Even though it probably doesn't matter about the speed at which we square numbers (there are much better optimisations to make), I decided to test it anyway. I wrote this program:

using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("This program tests the performance of squaring numbers.\n");
        Console.WriteLine("Iterations | a*a Time | Math.Pow(a, 2) Time");
        Console.WriteLine("-----------|----------|--------------------");

        int iterations = 100000;
        double number = 3092d;
        double result;

        while(true)
        {
            Stopwatch timera = Stopwatch.StartNew();

            for(int i = 0; i < iterations; i++)
            {
                result = number*number;
            }
            timera.Stop();

            Stopwatch timerb = Stopwatch.StartNew();
            for(int i = 0; i < iterations; i++)
            {
                result = Math.Pow(number, 2);
            }
            timerb.Stop();

            Console.WriteLine(" {0,9} | {1,8} | {2}", iterations, timera.ElapsedMilliseconds.ToString(), timerb.ElapsedMilliseconds.ToString());

            iterations += 100000;

            System.Threading.Thread.Sleep(500); // make sure that we don't crash the server
        }
    }
}

(pastebin, binary)

I didn't have a Windows Machine handy when writing this post, so the binary has been compiled with mono's dcms. Please leave a comment below if it doesn't work for you.

Everything is done with doubles to maek it a fair test because C♯'s Math.Pow method will only accept a double. The code sleeps for half a second between runs because I was writing this on the server that is serving the websitee, and I didn't want to crash it by accident :)

The results were rather shocking. The easiest way to display the results is in a graph:

A graph of the results.

A pastebin of the results can be found here.

As you can quite clearly see, Math.Pow() is horribly inefficient compared to just multiplying a number by itself. Next time I am squaring numbers, I won't be using Math.Pow again.

New Coding Conundrums

I have just discovered that the Coding Conundrums 3 has been released by Rob Miles on his Python Site. He hasn't put it up on the Coding Sharepoint site yet, so I thought that I would post about it here since I didn't notice until now.

Link to PDF: Coding Conundrums 3

Edit: I will be posting my solutions to the new set of Coding Conundrums just ass soon as I have completed them :)

Edit 2: They are up on the sharepoint site now.

Protecting your Privacy Online: Reviewing which Advertisers Track your Interests

This is a different kind of post about privacy on the web.

The youronlinechoices.com website

Protecting your privacy whilst browsing online is important. Most if not all advertisers will track you and the websites you visit to try and work out what you are interested in - The amount of information that advertising networks can accumulate is astonishing! I currently have an AdBlocker installed with a tracking prevention list enabled, but that isn't always enough to stop all the advertising networks from tracking you all the time.

Recently I have come across a website called youronlinechoices.com - a website for people in the EU that allows you to review and control which out of 96(!) advertising networks are currently tracking you and your interests. I found that about two dozen advertisers were tracking me and was able to stop them.

The Internet needs adverts in order for it to stay free for all (disable your adblocker on the sites you want to support), but one also needs to prevent ones personal information from falling into the wrong hands.

Learning Three.js three: Texturing

Three.js three

This week I have been busy, but I have still had time to create a new Three.js experiment. This week, I looked into simple texturing. The Cube in the middle has a simple soil texture, and I gave the skybox a bunch of clouds from opengameart.org. It took a whole lot of fiddling to get it to display the way it has now - I couldn't figure out the correct rotation for the tiles :D

This experiment also uses orbitcontrols.js from here I think? Click and drag to move around, and scroll up / down to zoom.

I have attempted to optimise it by only rendering a frame when the camera is actually moved or a texture is loaded too.

You can find it here: three

Art by Mythdael