Computer club Part 1

I was a kid in the 80’s, the short-lived golden era of Home Computers. I had a Sinclair ZX81, followed by a ZX Spectrum 48K (and another one when that one broke). At the same time I also had access to a very nice Commodore CBM 8032 and a BBC Model B at junior school. Later at home we got an Acorn Archimedes A440, later replaced with an Acorn RISC PC. At my senior school at the time, we had BBC’s, later replaced with a whole suite of Archimedes Machines.

Most these computers shared a common feature – when you booted them they presented you with a BASIC prompt. You were expected to enter code. Most children at the time could write a two line program (you know, the one that starts with 10 PRINT and fills the screen of the TRS80 in Tandy with rude words), and the computer rooms were usually fairly busy with people writing code. Even the Archimedes, recognisable to a present day user as a “proper” computer, had the superb BBC BASIC V right under the skin.

I spent a lot of my childhood tapping out code, and ended up working as software developer. Would I have done the same without these funny little computers? Who knows! We had no formal computer teaching of any kind at school. If you were lucky, there was an enthusiast teacher who might be able to answer a question. No Google either of course!

Unless you live under a rock (or outside the UK) you’ll have noticed the sudden rush of media coverage on the topic of ICT and IT teaching in schools. To me it felt like it all started in the media when Eric Schmidt criticised the British education system. I’ve been moaning about this to anyone that will listen for a several of years now, but actually did nothing more than that. Thank god some people have been more organised: the Raspberry Pi foundation (including the legendary David Braben), the Next Gen Skills group, Ian Livingstone (of Fighting Fantasy fame) and Alex Hope of Double Negative who co-authored the Next Gen report, the Royal Society’s “Shut Down or Restart?” report, the Computing at Schools working group (who published a rather good free suggested computing curriculum (PDF), the Goto FoundationRory-Cellan Jones (the BBC technology correspondent), the Guardian’s Digital Literacy Campaign, and probably other I’ve missed. The tireless efforts of these campaigners got the media covering the issue, and that meant the government had to respond, which they duly did.

There’s a lot more work to do, but it’s wonderful to see the energy and enthusiasm erupting here. I also think it’s wise to be cautious about the government’s response, and to recognise the good work that’s already being done in schools.

I mention all this as background, because I currently live in a school. It’s a boarding school, and my wife is a teacher here. In addition, we are both house parents which means we look after a bunch of boarders. I also have a day job in software.  For a long time, I’ve wanted to run some kind of computer club or activity, to find the potential geeks and programmers here and encourage them. This term, I’ve committed to doing it. The first one is today!
I’ve already hit a bunch of problems:
  • The ICT suite has all XP machines, very locked down, and it’s hard to install any software on them.
  • They only have IE installed, which rules out a lot of good web-based material.
  • The network uses a problematic (in the words of the IT Administrator) firewall/filter appliance which makes it hard to access sites, since every domain they hit has to be whitelisted.
Even at this late stage, I’m trying to figure out what we should be doing and how we should organise the sessions. They will be once a week, about 45 minutes long. I hope I’ll have pretty much the same people each week, from years 6-8.
The group will be self-selecting, in that the children choose these activities. This means I’ll be working with kids who are either good with computers, or who want to be, or think they might be (or want to be with their friends who are). I’ve no idea how many I’ll get, or how many will stick with it.
I intend to keep writing about this as I go along, but a few issues I can see on the horizon are:-
  • How to set up a platform I can really work with on the machines, without causing problems for the IT staff.
  • What to cover. I think I will have to play this by ear, depending on how many turn up, what their skills are and what the are interested in.
  • How to give the kids a way to carry on the activity between weekly sessions.
  • How inclusive it should be.

This last point is one that bothers me most, going in to it. Programming is quite hard, and requires patience and dedication. Some of them will probably have big, unrealistic expectations about what they can achieve, and I need to adjust those gently without putting them off.

When I was a kid, I got a buzz out of figuring a puzzle out, cracking something new, making a piece of code work no matter how simple.  That buzz is the payoff that you need to keep you there through all the frustration and effort you have to put in.  If you don’t get that, I don’t think you’ll go on to be a developer.

So, I hope I’ll get a few in the group who are the real deal; potential software developers. What about the rest? Do I try to put them off? Keep them entertained and hope a few things will stick? Because this is a club, not a lesson, I can play by different rules. While I believe some of this should be in the curriculum, and that all kids should get a grounding in it, this is an enthusiast group.

The ones who are the few who will stick with it will probably be happy writing Python code to print the Fibonacci sequence. The ones that aren’t will want whizz bang eye-candy to keep their interest going.

So how to balance it? Can we keep everyone happy?

Any advice welcomed!

C# helper to dump any object to a log

Some time back I had the need for code to make a reasonable go at dumping out any object into a debug log. Visual Studio does a good job of inspecting objects, so I figured there was probably a clever trick somewhere to achieve this easily, but I couldn’t find one. In the end, I wrote my own, and learned a bit more about reflection in the process.

My first attempt was useful but a bit fragile. Often it would fail horribly on a new class and I’d have to decorate the class with my custom attributes to make it work.

Since then I’ve refined it a fair amount, and it seems pretty stable although I’m sure it’s neither complete nor perfect. You get better output if you use the custom attributes here and there, but they shouldn’t be required. I use it in lots of my code and works well for me, so I share it here in case it’s more widely useful.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Common.Logging;

namespace DebugTools
{        
    public interface IDebugDumpMask
    {
        bool GetMask(string MemberName);
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class DumpClassAttribute : System.Attribute
    {

        public DumpClassAttribute()
        {
            IsEnumerable = false;
            ForceUseToString = false;
        }

        /// <summary>
        /// Forces the class to be treated as an enumerable type. Default false.
        /// </summary>
        public bool IsEnumerable { get; set; }
        /// <summary>
        /// Forces a simple string conversion of the object. Default false.
        /// </summary>
        public bool ForceUseToString { get; set; }
    
    }

    // Note: Visibility takes priority over masking
    // If an member is not visible, it will never be included.
    // A visible member can be masked out.

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    public class DumpMemberAttribute : System.Attribute
    {
 
        public DumpMemberAttribute()
        {
            IsVisible = true;
            MemberName = null;
            IsEnumerable = false;
            ForceUseToString = false;
            EscapeString = false;
        }

        /// <summary>
        /// Controls whether the member is included in the output or not. Default true for public members, false for private ones.
        /// </summary>
        public bool IsVisible { get; set; }
        /// <summary>
        /// Overrides the automatically derived memeber name
        /// </summary>
        public string MemberName { get; set; }
        /// <summary>
        /// Forced the member to be treated as an enumerable type. Default false.
        /// </summary>
        public bool IsEnumerable { get; set; }
        /// <summary>
        /// Forces a simple string conversion of the member. Default false.
        /// </summary>
        public bool ForceUseToString { get; set; }
        /// <summary>
        /// If true, the string is escaped before outputting.
        /// </summary>
        public bool EscapeString { get; set; }
    }

    public class DebugDumper
    {
        private static int RecursionCount = 0;

        private static DumpClassAttribute GetDebugDumpClassAttribute(Type cls)
        {
            object[] attributes = cls.GetCustomAttributes(typeof(DumpClassAttribute), true);
            foreach (object attr in attributes)
            {
                if (attr is DumpClassAttribute)
                    return (DumpClassAttribute)attr;
            }
            return null;

        }

        private static DumpMemberAttribute GetDebugDumpAttribute(MemberInfo member)
        {
            object[] attributes = member.GetCustomAttributes(typeof(DumpMemberAttribute), true);
            foreach (object attr in attributes)
            {
                if (attr is DumpMemberAttribute)
                    return (DumpMemberAttribute)attr;
            }
            return null;

        }

        private static Dictionary<string, string> Enumerate(object o, string baseName)
        {
            //logger.Trace("Enumerate {0}",baseName);

            RecursionCount++;

            if (RecursionCount > 5)
                Debugger.Break();

            var members = new Dictionary<string, string>();

            var ddc = GetDebugDumpClassAttribute(o.GetType());

            bool ForceEnum = CheckForcedEnumerable(o.GetType());

            if (ForceEnum || (ddc != null && ddc.IsEnumerable))
            {
                ProcessEnumerable(members, o, baseName);
            }
            else if (ddc != null && ddc.ForceUseToString)
            {
                members.Add(baseName, o.ToString());
            }
            else
            {

                BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

                FieldInfo[] fi = o.GetType().GetFields(flags);
                PropertyInfo[] pi = o.GetType().GetProperties(flags);

                ProcessFields(o, baseName, members, fi);
                ProcessProperties(o, baseName, members, pi);
            }

            RecursionCount--;

            return members;
        }

        private static bool CheckForcedEnumerable(Type type)
        {
            if (type.FullName.StartsWith("System.Collections.Generic.List"))
                return true;
            if (type.FullName.StartsWith("System.Collections.Generic.Dictionary"))
                return true;
            if (type.IsArray)
                return true;
            return false;
        }

        private static void ProcessProperties(object o, string baseName, Dictionary<string, string> members, PropertyInfo[] pi)
        {
            DumpMemberAttribute dd;
            IDebugDumpMask masker = o as IDebugDumpMask;
            bool mask;

            foreach (PropertyInfo prop in pi)
            {
                // Default is to show properties always
                dd = GetDebugDumpAttribute(prop) ?? new DumpMemberAttribute() { MemberName = prop.Name, IsVisible = true };
                mask = masker == null ? true : masker.GetMask(prop.Name);

                if (dd.IsVisible && mask)
                {
                    int IndexerCount = prop.GetIndexParameters().Count();
                    if (IndexerCount == 0 || (dd != null && dd.IsEnumerable))
                        try
                        {
                            ProcessMember(members, dd, prop.Name, prop.GetValue(o, null), baseName);
                        }
                        catch (TargetInvocationException)
                        {
                        }

                    else
                        Debug.Assert(false, "Can't dump an indexed property!");

                }
            }
        }

        private static void ProcessFields(object o, string baseName, Dictionary<string, string> members, FieldInfo[] fi)
        {
            DumpMemberAttribute dd;
            IDebugDumpMask masker = o as IDebugDumpMask;
            bool mask;

            foreach (FieldInfo field in fi)
            {
                // The attribute might be null, so we need to get some defaults if it is
                dd = GetDebugDumpAttribute(field) ?? new DumpMemberAttribute() { MemberName = field.Name, IsVisible = field.IsPublic };
                mask = masker == null ? true : masker.GetMask(field.Name);

                if (dd.IsVisible && mask)
                {
                    try
                    {
                        ProcessMember(members, dd, field.Name, field.GetValue(o), baseName);
                    }
                    catch (TargetInvocationException)
                    {
                    }

                }
            }
        }

        private static void ConcatSubMembers(Dictionary<string, string> members, Dictionary<string, string> subMembers)
        {
            foreach (KeyValuePair<string, string> item in subMembers)
            {
                members.Add(item.Key, item.Value);
            }
        }

        private static void ProcessMember(Dictionary<string, string> members, DumpMemberAttribute attribute, string memberName, object value, string baseName)
        {
            //logger.Trace("ProcessMember {0} : {1}", baseName, memberName);

            string name = string.Format("{0} : {1}", baseName, attribute.MemberName ?? memberName);

            if (value == null)
            {
                members.Add(name, "<null>");
            }
            else
            {
                Type type = value.GetType();
                if (type.IsArray || attribute.IsEnumerable)
                {
                    ProcessEnumerable(members, value, name);
                }
                else if (type.IsValueType || type == typeof(System.String) || attribute.ForceUseToString)
                {
                    members.Add(name, attribute.EscapeString ? EscapeString(value.ToString()) : value.ToString());
                }
                else if (type.IsClass)
                {
                    var subMembers = Enumerate(value, name);
                    ConcatSubMembers(members, subMembers);
                }
                else if (type.IsInterface)
                {
                    members.Add(name, type.ToString());
                }
            }
        }

        private static void ProcessEnumerable(Dictionary<string, string> members, object value, string name)
        {
            IEnumerable e = value as IEnumerable;
            value.GetType();
            int count = 0;

            foreach (object o in e.Cast<object>())
            {
                var member = string.Format("[{0}]", count);
                var dd = new DumpMemberAttribute() { IsVisible = true, MemberName = member };
                ProcessMember(members, dd, member, o, name);
                count++;
            }

        }

        public static List<string> Dump(object o, string baseName)
        {
            RecursionCount = 0;

            Dictionary<string, string> members = Enumerate(o, baseName);

            int maxLength = members.Keys.Select(x => x.Length).Max();

            return members.Select(x => (string.Format("{0} = {1}", x.Key.PadRight(maxLength + 1), x.Value))).ToList();

        }

        /// <summary>
        /// Take a string and create a version with all wierd characters escaped
        /// </summary>
        /// <param name="input">The string to escape</param>
        /// <returns>The escaped string</returns>
        public static string EscapeString(string input)
        {
            StringBuilder result = new StringBuilder();
            string wellknown = "\r\n\t\0\\";
            string wellknownmap = @"rnt0\";
            int ix;

            foreach (char c in input)
            {

                ix = wellknown.IndexOf(c);
                if (ix >= 0)
                {
                    result.Append(@"\" + wellknownmap[ix]);
                }
                else if (char.IsControl(c))
                {
                    result.AppendFormat(@"\x{0:x4}", (int)c);
                }
                else
                {
                    result.Append(c);
                }
            }

            return result.ToString();
        }
    }
}

To use it, just call Dump(), passing the object to dump and a base name to use in the output.
Apply the DumpMemberAttribute to members to change their behaviour when being processed.
Apply the DumpClassAttribute to classes to do the same.
Objects can also implement the IDebugDumpMask interface in order to customise the visibility of their members using more complex logic, if required.

Enjoy!

Technology report

Dilbert.com

When Dilbert is good, it’s perfect.

Using kexec for a fast reboot in Archlinux

If you ever wondered how some distros achieve the trick of bypassing the BIOS when rebooting, it’s done using something called kexec, which wikipedia defines as:

[…]a mechanism of the Linux kernel that allows “live” booting of a new kernel “over” the currently running kernel. kexec skips the bootloader stage (hardware initialization phase by the firmware or BIOS) and directly loads the new kernel into memory, where it starts executing immediately.

In archlinux, you can achieve this with the package kexec-tools, which you can install as usual with:
pacman -S kexec-tools

kexec-tools is integrated with the archlinux initscripts, so that the kexec command line tool will by default go through the normal shutdown procedure before rebooting. You can find more information as ever on the excellent Archlinux Wiki. There are some scripts there which look pretty useful, but I started using kexec direct from the command line after reading the man page, and then wrote a short script to cover the form I was using each time.

#!/bin/dash

imgname=/boot/kernel26${1:+-$1}
krnname=/boot/vmlinuz26${1:+-$1}

exec kexec --type=bzImage --reuse-cmdline --initrd=$imgname.img $krnname

I saved this as ~/bin/kxreboot. You can either just use this without parameters to boot the default kernel, or you can add a single parameter – for example, if you do kxreboot mainline it will boot vmlinuz26-mainline with initrd kernel26-mainline.img

You might also ask, “Why would I want a fast reboot? I never reboot!”. Fair comment. I run the testing repos, so kernel and udev upgrades come along quite frequently. Also, my motherboard doesn’t recognise my USB keyboard on boot, which makes a BIOS boot a bit of a pain as I have to find a PS/2 keyboard. Last but not least, everyone loves faster, right?

Blum Blum Shub in python

This is a python implementation of the excellently named “Blum Blum Shub” algorithm for generating pseudorandom numbers. See the wikipedia article for more information. This algorithm is good for use in cryptography, but due to its relatively slow speed, its not ideal for simulations.

The primes code came from www.4dsolutions.net/. I’m honestly not sure what the licence for that code is so the best I can do is to credit the site and thank them for the excellent resources they put online!


"""
Adapted from http://javarng.googlecode.com/svn/trunk/com/modp/random/BlumBlumShub.java

Original license follows:-

Copyright 2005, Nick Galbreath -- nickg [at] modp [dot] com
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   Neither the name of the modp.com nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This is the standard "new" BSD license:

http://www.opensource.org/licenses/bsd-license.php

"""

import primes;
import random;
import sys;

class BlumBlumShub(object):


    def getPrime(self, bits):
        """
        Generate appropriate prime number for use in Blum-Blum-Shub.
         
        This generates the appropriate primes (p = 3 mod 4) needed to compute the
        "n-value" for Blum-Blum-Shub.
         
        bits - Number of bits in prime

        """
        while True:
            p = primes.bigppr(bits);
            if p%4 == 3:
                break
        return p

    def generateN(self, bits):
        """
        This generates the "n value" for use in the Blum-Blum-Shub algorithm.
       
        bits - The number of bits of security
        """
    
        p = self.getPrime(bits/2)
        q = self.getPrime(bits/2)

        # make sure p != q (almost always true, but just in case, check)
        while p == q:
            q = getPrime(self, bits/2);
        
        # print "GenerateN - p = " + repr(p) + ", q = " + repr(q)            
        return p * q;
    

    def __init__(self, bits):
        """
        Constructor, specifing bits for n.
         
        bits - number of bits
        """        
        self.n = self.generateN(bits)
        # print "n set to " + repr(self.n)
        length = self.bitLen(self.n)
        seed = random.getrandbits(length)
        self.setSeed(seed)  

    def setSeed(self, seed):
        """
        Sets or resets the seed value and internal state.
         
        seed -The new seed
        """
    
        self.state = seed % self.n
    
    def bitLen(self, x):
        " Get the bit lengh of a positive number" 
        assert(x>0)
        q = 0 
        while x: 
            q = q+1 
            x = x>>1 
        return q     

    def next(self, numBits):
        "Returns up to numBit random bits"
        
        result = 0
        for i in range(numBits,0,-1):
            self.state = (self.state**2) % self.n
            result = (result << 1) | (self.state&1)
        
        return result    

def main():
    
    bbs = BlumBlumShub(128);
        
    #print "Generating 10 numbers"
    
    print "type: u"
    print "numbit: 32"
    print "count: 5000000"
    for i in range (0,5000000):
        print bbs.next(32)
            
if __name__ == "__main__":
    main()


"""
From http://www.4dsolutions.net/cgi-bin/py2html.cgi?script=/ocn/python/primes.py
"""

import random

def bigppr(bits=256):
    """
    Randomly generate a probable prime with a given
    number of hex digits
    """
     
    candidate = random.getrandbits(bits)

    if candidate&1==0:
        candidate += 1
    prob = 0
    while 1:
        prob=pptest(candidate)
        if prob>0: break
        else: candidate += 2
    return candidate
        
def pptest(n):
    """
    Simple implementation of Miller-Rabin test for
    determining probable primehood.
    """
    bases  = [random.randrange(2,50000) for x in range(90)]

    # if any of the primes is a factor, we're done

    if n<=1: return 0
    
    for b in bases:
        if n%b==0: return 0
        
    tests,s  = 0L,0
    m        = n-1

    # turning (n-1) into (2**s) * m

    while not m&1:  # while m is even

        m >>= 1
        s += 1
    for b in bases:
        tests += 1
        isprob = algP(m,s,b,n)
        if not isprob: break
            
    if isprob: return (1-(1./(4**tests)))
    else:      return 0

def algP(m,s,b,n):
    """
    based on Algorithm P in Donald Knuth's 'Art of
    Computer Programming' v.2 pg. 395 
    """
    result = 0
    y = pow(b,m,n)    
    for j in range(s):
       if (y==1 and j==0) or (y==n-1):
          result = 1
          break
       y = pow(y,2,n)       
    return result

Using LXDE or PCManFM? Desktop vanished?

Some changes in the most recent version may have caused your desktop icons and wallpaper to vanish. As the author notes here this is down to major changes going on behind the scenes.

To get get your desktop back, you need to run “pcmanfm –desktop”. To configure the settings which used to be in the Edit->Preferences menu, right-click on the desktop area and select Properties.

If you use openbox or similar, you’ll need to tick the option in there which causes the window manager’s menu to appear when the desktop is clicked. That then hides the pcmanfm desktop config! Luckily there’s an answer to that. Add an option to your WM menu (e.g. Openbox’s rc.xml) with an entry that calls “pcmanfm –desktop-pref”. This will allow you to edit the settings again.

Baudot fun

This is a throwaway piece of code, so it’s probably buggy but what the heck!


#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys

zero = '○'
one = '●'

numbers = []

def int2bin(n, count=5):
    """returns the binary of integer n, using count number of digits"""
    return "".join([ zero if ((n >> y) & 1) == 0 else one for y in range(count-1, -1, -1)])

def write(code):
    print numbers1

def output(newstate, curstate, code):

    figs = 27
    ltrs = 31

    if newstate == 0 and curstate == 1:
        write(ltrs)
    elif newstate == 1 and curstate == 0:
        write(figs)

    write(code)

    return newstate

def translate(input):
    global numbers

    numbers = map(int2bin,range(0,32))
    baudot_letters = '@E@A SIU@DRJNFCKTZLWHYPQOBG@MXV@'
    baudot_symbols = '@3@- @87@$4\',!:(5")2@6019?&@./;@'

    cr = 8
    lf = 2
    sp = 4
    state = 0

    for c in input.upper():
        if c == '@':
            continue
        if c == ' ':
            output(0,0,sp)
        elif c == '\n':
            output(0,0,cr)
            output(0,0,lf)
        else:
            ix = baudot_letters.find(c)
            if ix != -1:
                state = output(0, state, ix)
            else:
                ix = baudot_symbols.find(c)
                if ix != -1:
                    state = output(1, state, ix)

if __name__ == '__main__':
    for arg in sys.argv[1:]:
        translate(arg)

In case you're wondering, the Baudot code was invented in 1870 by Émile Baudot and later became the foundation of the international telex alphabets. See http://en.wikipedia.org/wiki/Baudot_code.

The original telex machines were electro-mechanical beasts which used this 5-bit code for wire transmission. Telex machines could encode text to punched tape for later sending. They could also print incoming telex transmissions to tape as well as paper. I remember seeing in a post bureau in Pakistan a journalist receiving a message on one telex machine and feeding the output spool of tape into another as it arrived. An early version of message forwarding!

Example output of the above:

johncc@liberator:~$ python baudot.py 'Hello world!'
●○●○○
○○○○●
●○○●○
●○○●○
●●○○○
○○●○○
●○○●●
●●○○○
○●○●○
●○○●○
○●○○●
●●○●●
○●●○●


Top artists this week from Last.fm

My Twitter feed


Follow

Get every new post delivered to your Inbox.