<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Cordinc Blog</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.cordinc.com/blog/atom.xml" />
    <id>tag:www.cordinc.com,2008-02-05:/blog//1</id>
    <updated>2010-03-07T16:23:16Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Personal 4.1</generator>

<entry>
    <title>Is there free money crossing Betfair and Betdaq?</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/03/is-there-free-money-crossing-b.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.96</id>

    <published>2010-03-06T20:39:35Z</published>
    <updated>2010-03-07T16:23:16Z</updated>

    <summary> It was recently suggested to me that there could be risk-free money to be made crossing Betfair and Betdaq. Betfair and Betdaq are betting exchanges - they allow their users to bet on various events, from the traditional horse...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="gambling" label="Gambling" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> It was recently suggested to me that there could be risk-free money to be made crossing <a href="http://www.betfair.com">Betfair</a> and <a href="http://www.betdaq.com">Betdaq</a>. Betfair and Betdaq are betting exchanges - they allow their users to bet on various events, from the traditional horse races to more unusual fare like netball or the UK general election. Unlike a normal bookmaker, the exchanges don't provide the odds and take the opposing side of the bet. Instead the odds are determined by other users and the other side is another user. So while there may be someone offering 1.15 odds that Labour will win (a <a href="http://help.betfair.com/contents/itemId/i65767719/index.en.html">back bet</a>) the next UK election, someone else may offer 1.2 that they will lose (a <a href="http://help.betfair.com/contents/itemId/i65767719/index.en.html">lay bet</a>). When the back and lay odds match then a bet is made. Note, all the odds quoted in this article are <a href="http://en.wikipedia.org/wiki/Fixed-odds_betting#Decimal_odds">decimal odds</a> as this is the type of odds used on the exchanges.</p>]]>
        <![CDATA[<p>While Betdaq and Betfair are two different companies and run their own separate exchanges, there is a great deal of overlap in the events on which they allow betting. Thus it is possible that the lay odds on one exchange are less than the back odds on the other. If this is the case, then by placing a lay bet on one and a back bet on the other, a profit will be made regardless of the actual result. For example, in theory, if I back Labour to win the next election for £10 at 1.2 odds then I profit $2 if Labour wins and lose $10 if they lose. If I lay Labour to win the next election for £10 at 1.1 odds, then I lose £1 if they win and profit £10 if they win. If I can make both bets at the same time, then if Labour wins I profit £1 (£2 from the back bet minus £1 from the lay) and if they lose I'm even (£10 loss on the back and £10 gain on the lay). Risk free <a href="http://en.wikipedia.org/wiki/Arbitrage">arbitrage</a>! </p>

<p>A friend watched the two exchanges manually and saw that occasionally the odds on the same event crossed. Does this mean there is money to be made? Let's see.</p>

In the general case, a back bet of size £X at P odds will cost £X, and in the event of a win return £XP, resulting in a profit of £X(P-1). For a lay bet of size £Y at Q odds, the cost is £Y(Q-1), if the bet wins then it returns £YQ for a profit of £Y. To hedge a back bet the cost of the back has to be matched by the profit on a lay, which according to the above means that X = Y (i.e. the lay bet has to be the same size as the back bet). If this hedge is to be profitable then the cost of the lay has to be less than the profit on the back. That is:<br />
<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 75px">


<pre>
       Y(Q-1) &lt; X(P-1) , but X=Y
    =&gt; X(Q-1) &lt; X(P-1) 
    =&gt;    Q-1 &lt; P-1 
    =&gt;      Q &lt; P
</pre>


</div>
Thus, as long as the lay odds are less than back odds it is possible to make a risk-free bet by hedging the back with an equivalent sized lay and the profit will the difference between the back &amp; lay odds multipled by the bet size.

So far so good, but the exchanges charge a fee on any winning bet (losing bets are free). For both exhanges this fee is expressed as a percentage of the profit on the bet and starts at 5% (although this can drop based on activity). How does this fee affect the equations above? Let Z be the fraction of the profit left after fees, that is if the fee is 5% of profit, Z=0.95. Then a back bet of size £X at P odds will cost £X and will result in a profit of £<acronym title="P-1">XZ</acronym> for a win. For a lay bet of size £Y at Q odds, the cost is £Y(Q-1), for a profit of £YZ. Thus to hedge a back, the back cost must equal the lay profit, X = <span class="caps">YZ.</span> The size of the lay has to be X/Z (which since Z has to be less or equal to 1, means the lay has to larger than the back). The hedge is profitable when:<br />
<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 110px">


<pre>
      cost of lay &lt; profit on back
           Y(Q-1) &lt; XZ(P-1) , but Y=X/Z
    =&gt; (X/Z)(Q-1) &lt; XZ(P-1) 
    =&gt;     X(Q-1) &lt; XZ^2(P-1) 
    =&gt;        Q-1 &lt; Z^2(P-1)
    =&gt;          Q &lt; Z^2(P-1)+1
</pre>


</div>

<p>This means that if the back odds are 1.2 then the lay odds have to be 1.18 (to 2 decimal places) at 5% fees and 1.19 at 2% fees. The difference between back and lay odds only diverges further from there. As shown in the graph below.<br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="cross_odds.png" src="http://www.cordinc.com/blog/images/cross_odds.png" width="520" height="300" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>

<p>Armed with this extra information I manually checked whether Betfair and Betdaq markets cross to this degree. While there are regular crosses, I never saw  the exchanges cross enough to make a profit.</p>]]>
    </content>
</entry>

<entry>
    <title>Societies in Transition</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/02/societies-in-transition.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.95</id>

    <published>2010-02-28T16:39:33Z</published>
    <updated>2010-02-28T20:42:08Z</updated>

    <summary> Available on iTunesU. I could not find a course website. This is a series of 8 anthropology lectures on the topic Socities in Transition recorded at Linacre College, Oxford University during early 2009. Each podcast is just under an...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="podcasts" label="Podcasts" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Available on <a href="http://deimos3.apple.com/WebObjects/Core.woa/Browse/ox-ac-uk-public.2006979775.02006979777">iTunesU</a>. I could not find a course website.</p>

<p>This is a series of 8 anthropology lectures on the topic Socities in Transition recorded at <a href="http://www.linacre.ox.ac.uk/Linacre">Linacre College, Oxford University</a> during early 2009. Each podcast is just under an hour and audio only (occasional mention is made of slides). Each lecture is given by a different presenter. All are fairly academic in nature (a couple are quite dry and I found it hard to maintain concentration), but are still accessible to the non-expert. These lectures are not straight history, there is little discussion of historical events. Instead each podcast presents current research on the process of social transition during a notable period of history. They often provide an interesting snapshot (or at least intriguing tidbits) of life around the time of the transition. </p>

<p>The lectures are in chronological order, spanning the entirity of human history - and beyond. The first lecture is on the <a href="http://en.wikipedia.org/wiki/Neanderthal">Neanderthals</a> - their slow extinction and modern discovery. The next lecture deals with the spread of farming in South East Asia. Then follows an interesting lecture on the spread of <a href="http://en.wikipedia.org/wiki/Metallurgy">metallurgy</a> in the <a href="http://en.wikipedia.org/wiki/Bronze_Age">Bronze Age</a> and what the metals meant to society at different times and places. Another interesting lecture details attempts to date and size the <a href="http://en.wikipedia.org/wiki/Minoan_eruption">volcanic explosion at Thera</a> (now <a href="http://en.wikipedia.org/wiki/Santorini">Santorini</a>). From this research the presenter trys to match up the likely effects with events and history in the region (mainly the <a href="http://en.wikipedia.org/wiki/Minoan_civilization">Minoan</a> society on Crete). The next two lectures are respectively on the beginning and end of <a href="http://en.wikipedia.org/wiki/Roman_Britain">Roman rule in Britain</a>. Apparently the collapse of the British economy after the Romans left was particularly swift - previously common pottery and coins disappeared almost overnight and buildings quickly fell into disrepair. The last two lectures are on more modern topics - the industrial and the current information revolutions.</p>

<p>Worth a listen for background information on the timeperiods discussed.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Tunisia Photos</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/02/tunisia-photos.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.94</id>

    <published>2010-02-21T11:43:02Z</published>
    <updated>2010-02-21T11:48:31Z</updated>

    <summary>A while ago I put up some photos from Dougga. Here are the best photos from the rest of that holiday in Tunisia. The set on Flickr is here....</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="travel" label="Travel" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>A while ago I put up some <a href="http://www.cordinc.com/blog/2008/12/dougga-photos.html">photos from Dougga</a>. Here are the best photos from the rest of that holiday in Tunisia. The <a href="http://www.flickr.com/photos/33547649@N07/sets/72157623353630109/show/">set on Flickr is here</a>.</p>

<p><a href="http://www.flickr.com/photos/33547649@N07/sets/72157623353630109/show/"><img src="http://farm5.static.flickr.com/4004/4375575858_ab49609d68.jpg" alt="" /></a></p>]]>
        
    </content>
</entry>

<entry>
    <title>JMX JConsole-like Connection Dialog</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/02/jmx-jconsolelike-connection-di.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.93</id>

    <published>2010-02-14T12:46:53Z</published>
    <updated>2010-02-21T18:05:06Z</updated>

    <summary>This is a quick post about a coding problem that took longer than expected to solve. I have put an example solution here as a reference for myself or others, hopefully speeding up the task. I needed to create a...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="java" label="Java" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="technical" label="Technical" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>This is a quick post about a coding problem that took longer than expected to solve. I have put an example solution here as a reference for myself or others, hopefully speeding up the task. I needed to create a dialog to connect to a local or remote <a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/"><span class="caps">JMX</span></a>  process. Essentially this would be very similar to the <a href="http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html">JConsole</a> "New Connection" dialog. Initially I thought this would just be a standard component, but instead it took some trial and error (as well as digging through Sun documentation) to get the required functionality working.</p>]]>
        <![CDATA[<p>The problematic parts are discovering which Java processes are running on the local computer and connecting to a local or remote <span class="caps">JMX </span>process. The code below will find local                <span class="caps">JMX </span>processes, by finding any <span class="caps">JVM</span>s running and trying to attach to them. Note that this code requires <a href="http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html">Sun's <span class="caps">JVM</span> Tool Interface</a> which is in tools.jar in the <span class="caps">JDK </span>lib folder (at least for <span class="caps">JDK6 </span>- not sure where it is in different versions).</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 100px">


<pre>
Map&lt;String, VirtualMachine&gt; result = new HashMap&lt;String, VirtualMachine&gt;();
List&lt;VirtualMachineDescriptor&gt; list = VirtualMachine.list();
for (VirtualMachineDescriptor vmd: list) {
   String desc = vmd.toString();
   try {
      result.put(desc, VirtualMachine.attach(vmd));
   } catch (IOException e) {
      e.printStackTrace(); 
   } catch (AttachNotSupportedException e) {
      e.printStackTrace(); 
   }
}
</pre>


</div>	
 <br />
To connect to a local <span class="caps">JMX </span>process after the VirtualMachine class for that process has been acquired, do the following:

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 100px">


<pre>
private JMXConnector getLocalConnection(VirtualMachine vm) throws Exception {
   Properties props = vm.getAgentProperties();
   String connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
   if (connectorAddress == null) {
      props = vm.getSystemProperties();
      String home = props.getProperty(&quot;java.home&quot;);
      String agent = home + File.separator + &quot;lib&quot; + File.separator + &quot;management-agent.jar&quot;;
      vm.loadAgent(agent);
      props = vm.getAgentProperties();
      connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
   }
   JMXServiceURL url = new JMXServiceURL(connectorAddress);
   return JMXConnectorFactory.connect(url);
}
</pre>


</div>

<p>The resulting <span class="caps">JMXC</span>onnector can be used in the normal way to retrieve data from <span class="caps">JMX </span>calls. For instance, if the <span class="caps">JMX </span>process exposed a no-arg function <tt>functionName</tt> on object <tt>objectName</tt>, the call would be:</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 75px">


<pre>
MBeanServerConnection mbsc = connector.getMBeanServerConnection();					
String result = (String)mbsc.invoke(new ObjectName(&quot;objectName&quot;),
                                     &quot;functionName&quot;, new Object[] {}, new String[] {});
</pre>


</div>

<p>Finding remote <span class="caps">JMX </span>processes is something you'll need to work out yourself, but assuming the host, port, user and password are known, the code to get a <span class="caps">JMXC</span>onnector is: </p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 120px">


<pre>
private JMXConnector getRemoteConnection(String host, int port, String user, String password) throws Exception {
   JMXServiceURL url = new JMXServiceURL(&quot;service:jmx:rmi:///jndi/rmi://&quot;+host+&quot;:&quot;+port+&quot;/jmxrmi&quot;);
   final Map&lt;String, String[]&gt; environment = new HashMap&lt;String, String[]&gt;();
   environment.put(JMXConnector.CREDENTIALS, new String[] {user, password} );
   return JMXConnectorFactory.connect(url, environment);
}
</pre>


</div>

<p>The resulting <span class="caps">JMXC</span>onnector can be used in the same manner as before. So with the above code it is just a matter of adding some <span class="caps">GUI </span>glue to create the required dialog. Excuse the <tt>main</tt> method and dodgy exception handling (and anything else) - this is just a quick example class.</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 500px">


<pre>
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

// requires Sun's default-tools.jar
public class JmxConnectorDialog extends JDialog implements ActionListener, KeyListener {

	private static final long serialVersionUID = 1L;
	private static final String CONNECTOR_ADDRESS_PROPERTY = &quot;com.sun.management.jmxremote.localConnectorAddress&quot;;
	
	private final JRadioButton localButton = new JRadioButton(&quot;Local Process&quot;);
	private final JRadioButton remoteButton = new JRadioButton(&quot;Remote Process&quot;);
	private final Map&lt;String, VirtualMachine&gt; localEngines = findEngines();
	private final JComboBox typeList = new JComboBox(localEngines.keySet().toArray());
	private final JTextField hostField = new JTextField(20);
	private final JTextField portField = new JTextField(20);
	private final JTextField userField = new JTextField(20);
	private final JPasswordField passField = new JPasswordField(20);
	
	private JMXConnector connector = null;
	private String errorString = &quot;&quot;;
	
	public static void main(String[] args) {
		JFrame frame = new JFrame(&quot;Graph Explorer&quot;);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        

	    JmxConnectorDialog jmxDialog = JmxConnectorDialog.showDialog(frame);
	    JMXConnector connector = jmxDialog.getConnector();
        if (connector==null) {
        	JOptionPane.showMessageDialog(frame,
	        	    &quot;Can't connect to JMX server: &quot;+jmxDialog.getError(),
	        	    &quot;Connection error&quot;, JOptionPane.ERROR_MESSAGE);
        } else {
        	JOptionPane.showMessageDialog(frame, &quot;Selected real Java process&quot;);
        }
   
        /*
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();
		String result = (String)mbsc.invoke(new ObjectName(&quot;objectName&quot;),
				&quot;functionName&quot;, new Object[] {}, new String[] {});			
        */
	}
	
	public static JmxConnectorDialog showDialog(Component frameComp) {
		Frame frame = JOptionPane.getFrameForComponent(frameComp);
		JmxConnectorDialog dialog = new JmxConnectorDialog(frame);
		dialog.setVisible(true);
		return dialog;
	}

	
	public JmxConnectorDialog(Frame frame) {
		super(frame, &quot;JMX Connection&quot;, true);
		addWindowListener(new WindowAdapter() {
			@Override public void windowClosing(WindowEvent e) {
				errorString=&quot;User cancelled&quot;;
				setVisible(false);
			}
		});
		
		Container contentPane = getContentPane();
		JPanel content = new JPanel();
		content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
		contentPane.add(content);
			
		content.add(createLocalPanel());
		content.add(createRemotePanel());
		content.add(createButtonPanel());
		
		ButtonGroup group = new ButtonGroup();
	    	group.add(localButton);
	    	group.add(remoteButton);
	  
		pack();
	}
	
	private JPanel createLocalPanel() {
		JPanel localPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
		localButton.setPreferredSize(new Dimension(150, 50));
		localButton.setSelected(true);
		localPanel.add(localButton);
		typeList.addActionListener(new ActionListener() {
			@Override public void actionPerformed(ActionEvent e) {
				localButton.setSelected(true);
			}			
		});
		JPanel listPanel = new JPanel(new FlowLayout());
		listPanel.add(typeList, BorderLayout.SOUTH);
		localPanel.add(listPanel);
		return localPanel;
	}
	
	private JPanel createRemotePanel() {
		JPanel remotePanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
		remoteButton.setPreferredSize(new Dimension(150, 50));
		remotePanel.add(remoteButton);
		JPanel remoteOptionPanel = new JPanel();
		remoteOptionPanel.setLayout(new BoxLayout(remoteOptionPanel, BoxLayout.Y_AXIS));
		remoteOptionPanel.add(createField(&quot;Host&quot;, hostField));
		remoteOptionPanel.add(createField(&quot;Port&quot;, portField));
		remoteOptionPanel.add(createField(&quot;User&quot;, userField));
		remoteOptionPanel.add(createField(&quot;Password&quot;, passField));
		remotePanel.add(remoteOptionPanel);
		return remotePanel;
	}
	
	private JPanel createButtonPanel() {
		JPanel buttonPanel = new JPanel(new FlowLayout());
		JButton connectButton = new JButton(&quot;Connect&quot;);
		getRootPane().setDefaultButton(connectButton);
		connectButton.addActionListener(this);
		buttonPanel.add(connectButton);
		JButton cancelButton = new JButton(&quot;Cancel&quot;);
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				errorString=&quot;User cancelled&quot;;
				setVisible(false);
			}
		});
		buttonPanel.add(cancelButton);
		return buttonPanel;
	}
	
	private JPanel createField(String label, JTextField field) {
		JPanel fieldPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 1));
		JLabel labelComponent = new JLabel(label);
		labelComponent.setPreferredSize(new Dimension(60, 10));
		fieldPanel.add(labelComponent);
		fieldPanel.add(field);
		field.addKeyListener(this);
		return fieldPanel;
	}
	
	private Map&lt;String, VirtualMachine&gt; findEngines() {
		Map&lt;String, VirtualMachine&gt; result = new HashMap&lt;String, VirtualMachine&gt;();
		List&lt;VirtualMachineDescriptor&gt; list = VirtualMachine.list();
		for (VirtualMachineDescriptor vmd: list) {
			String desc = vmd.toString();
			try {
				result.put(desc, VirtualMachine.attach(vmd));
			} catch (IOException e) {
				e.printStackTrace(); 
			} catch (AttachNotSupportedException e) {
				e.printStackTrace(); 
			}
		}	
		return result;
	}
	
	private JMXConnector getLocalConnection(VirtualMachine vm) {
		try {
			Properties props = vm.getAgentProperties();
			String connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
			if (connectorAddress == null) {
			   props = vm.getSystemProperties();
			   String home = props.getProperty(&quot;java.home&quot;);
			   String agent = home + File.separator + &quot;lib&quot; + File.separator + &quot;management-agent.jar&quot;;
			   vm.loadAgent(agent);
			   props = vm.getAgentProperties();
			   connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
			}
			
			JMXServiceURL url = new JMXServiceURL(connectorAddress);
			return JMXConnectorFactory.connect(url);
		} catch (Exception e) {
			e.printStackTrace();
			errorString = e.getMessage();
			return null;
		}
	}
	
	private JMXConnector getRemoteConnection(String host, int port, String user, String password) {
		try {
			JMXServiceURL url = new JMXServiceURL(&quot;service:jmx:rmi:///jndi/rmi://&quot;+host+&quot;:&quot;+port+&quot;/jmxrmi&quot;);
			final Map&lt;String, String[]&gt; environment = new HashMap&lt;String, String[]&gt;();
			environment.put(JMXConnector.CREDENTIALS, new String[] {user, password} );
	        return JMXConnectorFactory.connect(url, environment);
		} catch (Exception e) {
			e.printStackTrace();
			errorString = e.getMessage();
			return null;
		}
	}

	public JMXConnector getConnector() {
		return connector;
	}
	
	public String getError() {
		return errorString;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (localButton.isSelected()) {
			connector = getLocalConnection(localEngines.get(typeList.getSelectedItem()));
		} else {
			try {
				int port = Integer.parseInt(portField.getText());
				String password = String.valueOf(passField.getPassword());
				connector = getRemoteConnection(hostField.getText(), port, userField.getText(), password);
			} catch (NumberFormatException nfe) {
				JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), &quot;Invalid port number&quot;,
		        	    &quot;Connection error&quot;, JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		setVisible(false);
	}

	@Override
	public void keyPressed(KeyEvent e) {
		remoteButton.setSelected(true);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		remoteButton.setSelected(true);
	}

	@Override
	public void keyTyped(KeyEvent e) {
		remoteButton.setSelected(true);
	}
}
</pre>


</div>]]>
    </content>
</entry>

<entry>
    <title>Hannibal (Stanford Continuing Studies Program) </title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/02/hannibal-stanford-continuing-s.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.92</id>

    <published>2010-02-07T19:17:50Z</published>
    <updated>2010-02-21T18:11:46Z</updated>

    <summary> Available on iTunesU. I could not find a course website. These podcasts detail the life of the Carthaginian general Hannibal, often considered one of the greatest commanders of the ancient world. During the Second Punic War against the Roman...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="podcasts" label="Podcasts" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Available on <a href="http://deimos3.apple.com/WebObjects/Core.woa/Browse/itunes.stanford.edu.1374259372.01374259374">iTunesU</a>. I could not find a course website.</p>

<p>These podcasts detail the life of the <a href="http://en.wikipedia.org/wiki/Carthage">Carthaginian</a> general <a href="http://en.wikipedia.org/wiki/Hannibal">Hannibal</a>, often considered one of the greatest commanders of the ancient world. During the <a href="http://en.wikipedia.org/wiki/Second_Punic_War">Second Punic War</a> against the <a href="http://en.wikipedia.org/wiki/Roman_Republic">Roman Republic</a> in the 3rd century <span class="caps">BC,</span> Hannibal led his army over the Alps into Italy. He then used superior strategy and tactics to defeat the Roman army at a number of engagements, resulting in the battle of <a href="http://en.wikipedia.org/wiki/Battle_of_Cannae">Cannae</a> - a devastating loss for Rome. After this, the Romans adopted many of Hannibal's techniques. At the <a href="http://en.wikipedia.org/wiki/Battle_of_Zama">Battle of Zama</a>, Hannibal was defeated and Carthage lost the war.</p>

<p>The lectures were given by <a href="http://en.wikipedia.org/wiki/Patrick_Hunt">Patrick Hunt</a> as part of the <a href="http://www.continuingstudies.stanford.edu/">Stanford Continuing Studies Program</a> sometime during 2007. I couldn't find a course website, but there are a <a href="http://traumwerk.stanford.edu/archaeolog/2006/11/alpine_archaeology_hannibal_ex.html">few</a> <a href="http://traumwerk.stanford.edu/archaeolog/2006/04/hannibal_in_the_alps_stanford_1.html">articles</a> relating to the course. There are 8 lectures (strangely numbered 1 through 10), all of which are audio only and nearly two hours long (around 30MB in size). The first podcast is an interesting discussion on Carthaginian culture, in particular whether they really practiced <a href="http://en.wikipedia.org/wiki/Religion_in_Carthage#Child_sacrifice">child sacrifice</a>. The second lecture introduces the <a href="http://en.wikipedia.org/wiki/First_Punic_War">First Punic War</a> and Hannibal's father, <a href="http://en.wikipedia.org/wiki/Hamilcar_Barca">Hamilcar Barca</a>. The Second Punic War is covered over three lectures (along with an epilogue). The remaining three podcasts are dedicated to Hannibal's crossing of the Alps.</p>

<p>It seems Patrick Hunt organises regular expeditions to cross the Alps, trying to find archeological proof of where Hannibal crossed. Great attention is paid to how closely various mountain passes fit the ancient descriptions. Dr Hunt personally favours the <a href="http://en.wikipedia.org/wiki/Col_de_Clapier">Col de Clapier</a>. If this historical event is of interest,  then you will be well served. There is not one, not two, but three different first-person accounts of modern crossings of the Alps in attempts to follow Hannibal's footsteps: Hunt's; Ed Boenig, a student of Dr Hunt's; and John Hoyte's, who crossed the Col de Clapier in 1959 with an elephant (called <a href="http://www.archaeology.org/image.php?page=0701%2Fabstracts%2Fjpegs%2Fhannibal2.jpg">Jumbo</a>). </p>

<p>Apart from close concentration on a narrow historical time period, the series has many intriguing digressions. For instance, there is occasional mention of the meaning of Hannibal's name, "grace of Ba'al". <a href="http://en.wikipedia.org/wiki/Baal">Ba'al</a> was the main Carthaginian deity, who supposedly lived on a mountain. Thus Dr Hunt suggests Hannibal would have had no fear of mountains. A bit of a stretch, but still interesting. If you have a particular interest in finding out about Hannibal's crossing of the Alps, then this is the podcast for you. However, there is still much to learn even if that is not your focus (and the second two alpine lectures can be safely skipped). On the downside, the first lecture (on the origins of Carthage) seems to be missing. Also, there is no sign of the lecture slides. Being able to see the maps and slides would have been particularly useful during discussions of which Alpine pass most closely matched ancient descriptions. Nevertheless, don't be put off by the long podcast length, this series is well worth a listen.</p>]]>
        
    </content>
</entry>

<entry>
    <title>JButtons in a JTable</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/jbuttons-in-a-jtable.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.91</id>

    <published>2010-01-30T15:12:32Z</published>
    <updated>2010-01-31T10:37:14Z</updated>

    <summary>Recently I wanted to have a clickable button in a table. Searching on Google for JButton in JTable I found a couple of suggestions, most notably this DevX article and this Esus article. There was also a StackOverflow question that...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="java" label="Java" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="technical" label="Technical" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>Recently I wanted to have a clickable button in a table. Searching on Google for <a href="http://www.google.co.uk/search?q=JButton+in+JTable">JButton in JTable</a> I found a couple of suggestions, most notably this <a href="http://www.devx.com/getHelpOn/10MinuteSolution/20425">DevX article</a> and this <a href="http://www.esus.com/docs/GetQuestionPage.jsp?uid=1285">Esus article</a>. There was also a <a href="http://stackoverflow.com/questions/764417/is-it-possible-to-include-jbutton-in-a-jtable/">StackOverflow question</a> that just referenced other solutions. None really satisfied me. So borrowing their ideas I created my own solution.</p>]]>
        <![CDATA[<p>Fundamentally, there are two problems with having a JButton in a JTable. Firstly, by default a JTable will display cell values as a String, so JButtons appear as "javax.swing.JButton". Secondly, a JTable does not pass clicks through to the cells. </p>

<p>To display the buttons correctly a custom cell renderer needs to be applied to any columns displaying JButtons. This can be done with the code <tt>table.getColumn("Button1").setCellRenderer(new JTableButtonRenderer())</tt> (this assumes that there is a column in the table labelled "Button1". The button renderer is below. The default renderer always returns a JLabel, but this one returns a JButton after colouring it in an appropriate manner. Note, this renderer assumes the contents of column will always be a JButton and will throw an exception if this is not the case. If the table column may not contain JButtons, just extend <tt>DefaultTableCellRenderer</tt>, detect if the value is a JButton (or even a Swing component) with <tt>instanceof</tt>, otherwise call <tt>super</tt>. This <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer">Sun article</a> may help with this.</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 230px">


<pre>
public class JTableButtonRenderer implements TableCellRenderer {		
  @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    JButton button = (JButton)value;
    if (isSelected) {
      button.setForeground(table.getSelectionForeground());
      button.setBackground(table.getSelectionBackground());
    } else {
      button.setForeground(table.getForeground());
      button.setBackground(UIManager.getColor(&quot;Button.background&quot;));
    }
    return button;	
  }
}
</pre>


</div>

<p>To get the table to pass clicks through to the button, add a mouse listener to the table with <tt>table.addMouseListener(new JTableButtonMouseListener(table))</tt>. This mouse listener (example below) will have to take the click, work out in which cell it occurred and if that cell contains a JButton, click it.</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 270px">


<pre>
public class JTableButtonMouseListener extends MouseAdapter {
  private final JTable table;
		
  public JTableButtonMouseListener(JTable table) {
    this.table = table;
  }

  @Override public void mouseClicked(MouseEvent e) {
    int column = table.getColumnModel().getColumnIndexAtX(e.getX());
    int row    = e.getY()/table.getRowHeight(); 

    if (row &lt; table.getRowCount() &amp;&amp; row &gt;= 0 &amp;&amp; column &lt; table.getColumnCount() &amp;&amp; column &gt;= 0) {
      Object value = table.getValueAt(row, column);
      if (value instanceof JButton) {
        ((JButton)value).doClick();
      }
    }
  }
}
</pre>


</div>

<p>And with that, the buttons in your table should start to work. All you need to do is return the buttons (which perform the required actions) when requested from your model, using <tt>getValueAt()</tt>. A complete working example is below.</p>

<div style="background: #DFE8DF; overflow: auto; padding: 5px; margin-bottom: 10px; height: 600px">


<pre>
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class ButtonExample {

	public static void main(String[] args) {
		final ButtonExample example = new ButtonExample();
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            	example.createAndShowGUI();
            }
        });
	}
	
	private void createAndShowGUI() {
        JFrame frame = new JFrame(&quot;Button Example&quot;);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JTable table = new JTable(new JTableModel()); 
        JScrollPane scrollPane = new JScrollPane(table);
		table.setFillsViewportHeight(true);	
		
		TableCellRenderer buttonRenderer = new JTableButtonRenderer();
		table.getColumn(&quot;Button1&quot;).setCellRenderer(buttonRenderer);
		table.getColumn(&quot;Button2&quot;).setCellRenderer(buttonRenderer);
		table.addMouseListener(new JTableButtonMouseListener(table));
        
        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
        frame.getContentPane().setPreferredSize(new Dimension(500, 200));
        frame.pack();
        frame.setVisible(true);
	}
	
	public static class JTableModel extends AbstractTableModel {
		private static final long serialVersionUID = 1L;
		private static final String[] COLUMN_NAMES = new String[] {&quot;Id&quot;, &quot;Stuff&quot;, &quot;Button1&quot;, &quot;Button2&quot;};
		private static final Class&lt;?&gt;[] COLUMN_TYPES = new Class&lt;?&gt;[] {Integer.class, String.class, JButton.class,  JButton.class};
		
		@Override public int getColumnCount() {
			return COLUMN_NAMES.length;
		}

		@Override public int getRowCount() {
			return 4;
		}
		
		@Override public String getColumnName(int columnIndex) {
	        return COLUMN_NAMES[columnIndex];
	    }
		
		@Override public Class&lt;?&gt; getColumnClass(int columnIndex) {
			return COLUMN_TYPES[columnIndex];
		}

		@Override public Object getValueAt(final int rowIndex, final int columnIndex) {
			switch (columnIndex) {
				case 0: return rowIndex;
				case 1: return &quot;Text for &quot;+rowIndex;
				case 2: // fall through
				case 3: final JButton button = new JButton(COLUMN_NAMES[columnIndex]);
						button.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent arg0) {
								JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(button), 
										&quot;Button clicked for row &quot;+rowIndex);
							}
						});
						return button;
				default: return &quot;Error&quot;;
			}
		}	
	}

	private static class JTableButtonRenderer implements TableCellRenderer {		
		@Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			JButton button = (JButton)value;
			if (isSelected) {
				button.setForeground(table.getSelectionForeground());
				button.setBackground(table.getSelectionBackground());
		    } else {
		    	button.setForeground(table.getForeground());
		    	button.setBackground(UIManager.getColor(&quot;Button.background&quot;));
		    }
			return button;	
		}
	}
	
	private static class JTableButtonMouseListener extends MouseAdapter {
		private final JTable table;
		
		public JTableButtonMouseListener(JTable table) {
			this.table = table;
		}

		public void mouseClicked(MouseEvent e) {
			int column = table.getColumnModel().getColumnIndexAtX(e.getX());
			int row    = e.getY()/table.getRowHeight(); 

			if (row &lt; table.getRowCount() &amp;&amp; row &gt;= 0 &amp;&amp; column &lt; table.getColumnCount() &amp;&amp; column &gt;= 0) {
			    Object value = table.getValueAt(row, column);
			    if (value instanceof JButton) {
			    	((JButton)value).doClick();
			    }
			}
		}
	}
}
</pre>


</div>]]>
    </content>
</entry>

<entry>
    <title>Italy Photos</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/italy-photos.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.90</id>

    <published>2010-01-23T17:58:53Z</published>
    <updated>2010-01-23T17:59:55Z</updated>

    <summary>A while ago I put up some photos from Pompeii, and it is about time I put up the best photos from the rest of that holiday in Italy. The set on Flickr is here....</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="travel" label="Travel" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>A while ago I put up some <a href="http://www.cordinc.com/blog/2009/06/pompeii-photos.html">photos from Pompeii</a>, and it is about time I put up the best photos from the rest of that holiday in Italy. The <a href="http://www.flickr.com/photos/33547649@N07/sets/72157623143607329/show/">set on Flickr is here</a>.</p>

<p><a href="http://www.flickr.com/photos/33547649@N07/sets/72157623143607329/show/"><img src="http://farm3.static.flickr.com/2693/4298200246_7a8889c2ca.jpg" alt="" /></a></p>]]>
        
    </content>
</entry>

<entry>
    <title>History 110: Roman Republic</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/history-110-roman-republic.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.89</id>

    <published>2010-01-17T15:03:39Z</published>
    <updated>2010-01-31T11:05:14Z</updated>

    <summary> Available on iTunesU. I could not find a course website. Professor Isabelle Pafford from The Ancient Mediterranean World podcasts returns for another series of Ancient History podcasts. This time a course on the Roman Republic given during Fall 2008...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="podcasts" label="Podcasts" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Available on <a href="http://deimos.apple.com/WebObjects/Core.woa/Browse/scu.edu.1713297656.01713297664">iTunesU</a>. I could not find a course website.</p>

<p>Professor Isabelle Pafford from <a href="http://www.cordinc.com/blog/2009/12/history-4a-the-ancient-mediter.html">The Ancient Mediterranean World</a> podcasts returns for another series of Ancient History podcasts. This time a course on the Roman Republic given during Fall 2008 at <a href="http://www.scu.edu/">Santa Clara University</a>. There are 19 podcasts - 1 is a slide show video, but the others are audio only. Each podcast is around 50 minutes in length and around 50MB. In the audio podcasts there are often references to slides that are not available online. </p>

<p>The course starts with the stories of <a href="http://en.wikipedia.org/wiki/Founding_of_Rome">Rome's foundation</a> along with details of the surrounding area and people, which presumably influenced early Rome. The <a href="http://en.wikipedia.org/wiki/Roman_Kingdom">Roman Kingdom</a> is quickly passed over (perhaps due to a lack of information on the era) for the <a href="http://en.wikipedia.org/wiki/Roman_Republic">Roman Republic</a>. Most attention is focussed on the Late Republic, with over half the lectures on the period from the <a href="http://en.wikipedia.org/wiki/Gracchi">Gracchi</a> to <a href="http://en.wikipedia.org/wiki/Julius_Caesar">Caesar</a> - around 133BC to 49BC. </p>

<p>These lectures are full of engrossing details. There is a bit of historical timeline talk (on this date this happened and on that date that happened), but the series is more about the life and times of ancient Rome. For instance, there is often discussion of the <a href="http://en.wikipedia.org/wiki/Cursus_honorum">Cursus Honorum</a> (a series of military and administrative positions that provided a semi-formal structure to a political career) and how it affected the way people sought or achieved power. There was also a strong <a href="http://www.roman-empire.net/society/society.html#clients">patron-client</a> system, where a person's power could, in part, be measured by the number of clients/followers they had. Thus, manumission was common as freed slaves were typically clients of their previous owner. There is also some interesting consideration of which events are definitely known to have occurred, the fixed-points of history, and those parts of the <a href="http://en.wikipedia.org/wiki/Primary_source">primary sources</a> that may be apocryphal. </p>

<p>Professor Pafford can be an engaging speaker, and it is clear this is an area she knows well. Indeed the extra colour provided as cracks began to appear in the republic had me hooked. It was a classic fight between two political parties, the <a href="http://en.wikipedia.org/wiki/Optimates">Optimates</a> and <a href="http://en.wikipedia.org/wiki/Populares">Populares</a> - modern analogies are too easy to make. Although the ability to raise private armies and the tendency of losers to be executed adds an epic scale to proceedings. The final result may be well-known, with Caesar the unlikely Populares triumphing - but I still raced through the last half-dozen lectures.</p>

<p>It was a good thing I did know what happened in the end, as the end of the lecture series is missing (hint Caesar is assassinated and his nephew eventually dissolved the republic, becoming the first emperor, <a href="http://en.wikipedia.org/wiki/Augustus">Augustus</a>). I would guess that around a half-dozen of the lectures are unavailable, mainly around the mid-republic. At one point Professor Pafford apologises for losing some lectures in a hard-drive crash. So I suppose their absence is forgiveable. However, like the earlier Ancient Mediterranean podcasts, there are numerous other production issues. The audio quality is usually good, apart from a few notable exceptions. The video lecture is almost impossible to hear, and the slides are small relative to the screen. Another lecture on the <a href="http://en.wikipedia.org/wiki/First_Triumvirate">First Triumvirate</a> is split across two lectures because it sounds like the microphone failed (and the second part is very quiet). There is also quite a bit of course administrative talk (assignments, books, etc) - in one 40 minute lecture, 8 minutes are spent on such course administration topics. At least the class seem interested and ask some good questions. The lectures are also presented out of order on iTunes. It helps to know a bit of history to reorganise them from the titles.</p>

<p>Interesting history podcasts, again let down a little by production.</p>]]>
        
    </content>
</entry>

<entry>
    <title>New goals, again</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/new-goals-again.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.88</id>

    <published>2010-01-10T10:32:51Z</published>
    <updated>2010-01-31T10:51:00Z</updated>

    <summary>I don&apos;t like new year resolutions detailing plans to make yourself better - I&apos;m already great! However, I do like the idea of setting a few goals. This year&apos;s goals are fairly similar to last years, but a little less...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="general" label="General" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>I don't like new year resolutions detailing plans to make yourself better - I'm already great! However, I do like the idea of setting a few goals. This year's goals are fairly similar to last years, but a little less ambitious:</p>


<ul>
<li>Blog at an average rate of at least 4 times a month. Fairly sure I can do this with the <a href="http://www.cordinc.com/cgi-sys/cgiwrap/cordinc/managed-mt/mt-search.cgi?tag=Blender&amp;blog_id=1">Blender</a> and <a href="http://www.cordinc.com/cgi-sys/cgiwrap/cordinc/managed-mt/mt-search.cgi?tag=History&amp;blog_id=1">History Podcast</a> posts I'm planning.</li>
<li>Only have 2 programming projects going at the same time. Reassess projects every 3 months. The first two are: learning how to load and animate blender models in a 3D graphics engine; and a secret project. </li>
<li>Complete 3 Blender models and write tutorials on them - the models are a robot (to learn animation), a <a href="http://en.wikipedia.org/wiki/Thermopolium">Thermopolium</a>, and a <a href="http://en.wikipedia.org/wiki/Broch">Broch</a>.</li>
<li>Maintain Queuesaurus and general ruby skills. Try to use Scala.</li>
<li>Run 5km in 25 minutes. This is a bit ambitious.</li>
<li>Decrease net ownership of physical goods</li>
</ul>

]]>
        
    </content>
</entry>

<entry>
    <title>Recap</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/recap.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.87</id>

    <published>2010-01-09T12:07:31Z</published>
    <updated>2010-01-31T10:52:54Z</updated>

    <summary> Almost a year ago I wrote some goals for the new year. Now it is time for an assessment. Goal: Improve Ruby skills. Result: Partial success. I&apos;m not at what I would consider a professional standard, but not far...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="general" label="General" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Almost a year ago I wrote <a href="/blog/2009/02/new-goals.html">some goals for the new year</a>. Now it is time for an assessment.</p>


<ul>
<li><strong>Goal: Improve Ruby skills. Result: Partial success.</strong> I'm not at what I would consider a professional standard, but not far off it. I gemify'ed my <span class="caps">BBC </span>weather library, but have since abandoned it as keeping up with the <span class="caps">BBC'</span>s constant <span class="caps">API </span>changes was frustrating. I use <a href="http://www.queuesaurus.com">Queusaurus</a> even if no one else does. I started another project, but it didn't get far enough to publicise.</li>
<li><strong>Goal: Learn Scala. Result: Have done some, but not much.</strong> </li>
<li><strong>Goal: Learn Blender. Result: Near Success.</strong> I feel confident enough about this one. I haven't completed an ancient scene, but I'm sure I could.</li>
<li><strong>Goal: Decrease net ownership of physical goods. Result: Success.</strong> Doing this slowly but surely - I own fewer things now than when I wrote that goal, but not by much.</li>
<li><strong>Goal: 48 blog posts in a year. Result: 44 posts.</strong> I'm fairly happy with that. Holidays and looking for a new work contract slowed me down a bit.</li>
<li><strong>Goal: Run 5km in 25 minutes. Result: Not even close.</strong> The less said the better.</li>
<li>On the stretch goals, all are still a long distance away. </li>
</ul>




<p>I think the main problem with achieving those goals was my tendency to try doing too much. At one point (and continuing for a couple of months) I had 6 programming projects on the go at once. Nothing progressed at any pace over the last half of the year and that is what caused the most slippage. Something to be aware of for the coming year.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Starting a UK Company</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2010/01/starting-a-uk-company.html" />
    <id>tag:www.cordinc.com,2010:/blog//1.86</id>

    <published>2010-01-02T18:19:25Z</published>
    <updated>2010-01-02T18:57:57Z</updated>

    <summary> Having just completed the process of forming a new limited company under UK law, I found myself frustrated by the number of steps required. In case I ever need to do it again, or a reader does, I thought...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="entrepreneurship" label="Entrepreneurship" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Having just completed the process of forming a new <a href="http://en.wikipedia.org/wiki/Limited_company">limited company under UK law</a>, I found myself frustrated by the number of steps required. In case I ever need to do it again, or a reader does, I thought it might be useful to set out the steps I took - hopefully I haven't missed any! If it seems overwhelming, various accountancy or specialist firms can do most of it for a fee. Note, I am not an expert in this area, just someone who has done it once and recorded the steps - there is no guarantee this is completely correct.</p>


<ul>
<li>First get the company formed. This will require a unique company name, a business address, and directors' details. Forming the company can be done through <a href="http://www.companieshouse.gov.uk/">Companies House</a>, but I used <a href="http://www.companiesmadesimple.com">Companies Made Simple</a> to get things moving quickly. I recommend getting a Printed Certificate of Incorporation - it is needed in later steps.  </li>
<li>In my business, clients require invoices to have a <span class="caps">VAT </span>number so registering for <span class="caps">VAT </span>was my next step. If you don't need a <span class="caps">VAT </span>number straight away, you may wish to get a bank account first. Also, if the firm's turnover is less than £68,000, registration is not required. There are a few other exemptions too, see more at the <a href="http://www.businesslink.gov.uk/bdotg/action/layer?r.s=m&amp;r.l4=1073863071&amp;r.l1=1073858808&amp;r.lc=en&amp;r.l3=1083126677&amp;r.l2=1083126673&amp;topicId=1083126677&amp;r.i=1077722988&amp;r.t=BLTTOOL">Business Link <span class="caps">VAT </span>guide</a>. I applied for registration online through the <a href="https://online.hmrc.gov.uk/"><span class="caps">HMRC</span> Online website</a> (click register) - the details required should be the same as for company formation. <span class="caps">HMRC </span>also runs a <a href="http://www.hmrc.gov.uk/vat/start/schemes/flat-rate.htm">Flat Rate <span class="caps">VAT </span>scheme</a> that is worth investigating. If it turns out to be useful then applying to join the scheme can be done at the same time as registering for <span class="caps">VAT.</span></li>
<li>Get a bank account. This is quite important as many of the other steps need either bank details or a good reason why there are none (eg <span class="caps">VAT </span>registration). Most banks will require a Printed Certificate of Incorporation. I can't recommend any good banks, and you should be aware that it can take longer than you think to open a business account.</li>
<li>Sign up to file company documents online at <a href="http://www.companieshouse.gov.uk/">Companies House</a> (click on File documents online). Even if the information given during formation never change, the company will still need to submit at least two forms a year to Companies House to stay registered (annual return and annual accounts). This is easy to do online. At the same time you can sign up for the <a href="http://www.companieshouse.gov.uk/infoAndGuide/coIdFraud.shtml"><span class="caps">PROOF</span></a> system to make it harder for fraudsters to take control of the company by filing paper forms. However, be aware that once you have applied for online access, Companies House will (physically) mail some activation forms before you can file online.</li>
<li>If the company will be paying anyone a salary or expenses (directors' expenses count) then you will need to sign up to <span class="caps">PAYE.</span> This can be done up to a month before payment. Again this can be done through the <a href="https://online.hmrc.gov.uk/"><span class="caps">HMRC </span>website</a> (click register). From the employer's perspective, I find <span class="caps">PAYE </span>a bit complicated. You should learn about it yourself - <a href="http://www.hmrc.gov.uk/paye/intro/index.htm"><span class="caps">HMRC</span></a> and <a href="http://www.businesslink.gov.uk/bdotg/action/layer?r.s=m&amp;r.l1=1073858808&amp;r.lc=en&amp;topicId=1073858787">Business Link</a> are good places to start.</li>
<li>In the weeks after forming the company, <span class="caps">HMRC </span>should send you some forms to register for Corporate Tax. These need to be filled in and returned within 3 months of business activity starting. Filling in the forms will require the firm's <span class="caps">PAYE, VAT </span>details, and the Memorandum of Incorporation (this should have been included as part of the formation process).</li>
<li>Insurance may be required and is probably a good idea anyway. My business area requires Professional Indemnity Insurance, so I organised this before beginning trading. There are many other forms of insurance which may be useful - my firm also has Employers' Insurance and Public Liability Insurance. <a href="http://www.businesslink.gov.uk/bdotg/action/layer?r.s=sl&amp;r.lc=en&amp;topicId=1075196424">Business Link have a guide</a> to help determine which forms of insurance may be required. I used an industry specialist insurer, which wouldn't be useful to most readers, but I have learnt to shop around as different firms can quote vastly different rates (often the most expensive is multiples of the cheapest).</li>
<li>I recommend signing up to submit <span class="caps">VAT, PAYE </span>and Corporate Tax forms through the <a href="http://www.hmrc.gov.uk/"><span class="caps">HMRC </span>website</a>. It is quite good and normally guides you through the process of completing a form; facing a long paper form fills me with fear. Also, if <span class="caps">VAT </span>is paid by direct debit (which can be set up online) <span class="caps">HMRC </span>will give you an extra week to pay (this can be done for <span class="caps">PAYE </span>too). After initially applying online <span class="caps">HMRC </span>will send activation codes through the mail to complete the process.</li>
<li>Profit!</li>
</ul>



<p>After that I advise you quickly sort out your accounts and construct a calendar of regulatory/tax events. Remember, every 3 months a <span class="caps">VAT </span>form will need to be submitted. Depending on payroll size, <span class="caps">PAYE </span>will need to be paid monthly or once a year in addition to an annual <span class="caps">PAYE </span>form (P35) and expenses form (P11D). Corporate Tax forms need to be submitted annually, as do Companies House returns and accounts. Staying organised and being able to quickly determine the financial position of the firm is very useful. Since my business is fairly simple and having completed a course on accounting at uni, I created a double entry book-keeping system in Excel. If you don't feel you have the knowledge to do this (or the firm's accounts are too complicated) there are various software packages and accountants that can help - I can't recommend any. </p>

<p>In general, the <a href="http://www.hmrc.gov.uk/"><span class="caps">HMRC</span></a>  and <a href="http://www.businesslink.gov.uk">Business Link</a> websites are very useful and well worth a look.</p>

<p>Good luck!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Singularly Lazy</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2009/12/singularly-lazy.html" />
    <id>tag:www.cordinc.com,2009:/blog//1.85</id>

    <published>2009-12-20T19:40:29Z</published>
    <updated>2009-12-23T16:52:16Z</updated>

    <summary>Ah, the Singleton pattern. It is used to create a single, globally accessible instance of a class, preventing any further instantiations (so only one object of the class can ever exist). When I first learnt about Singletons soon after leaving...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="technical" label="Technical" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>Ah, the <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a> pattern. It is used to create a single, globally accessible instance of a class, preventing any further instantiations (so only one object of the class can ever exist). When I first learnt about Singletons soon after leaving university, I thought they were wonderful and used them often. Now I think that they are often a very bad idea. Not because of security concerns, as one person once suggested to me, but because I don't want static methods/classes hanging round (increasing global state) or I later realise more than one is needed!</p>

<p>Once when creating a consumer website for a bank I needed access to various pieces of bank information at numerous points in the code. "There is only one bank", I reasoned and made the class containing this information a singleton. Then the bank acquired another two banks so my design was broken and refactoring had to take place right before launch. However, despite learning repeatedly from experience, I still find myself creating more. I think this is due to laziness on my part. If I'm short of time or feel that it is not particularly important, I fall back on habit. Later, while refactoring I realise a better result could have been achieved with some thought. For instance, if the global access of singletons is a problem, perhaps using an <a href="http://en.wikipedia.org/wiki/Inversion_of_control">IoC</a> container (like <a href="http://www.springsource.org/about">Spring</a>) to wire everything up could help.</p>

<p>I hereby resolve not to use Singletons without thinking very hard first about whether there is a better way. </p>]]>
        
    </content>
</entry>

<entry>
    <title>History 4A: The Ancient Mediterranean World</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2009/12/history-4a-the-ancient-mediter.html" />
    <id>tag:www.cordinc.com,2009:/blog//1.84</id>

    <published>2009-12-14T09:40:36Z</published>
    <updated>2010-01-13T20:08:48Z</updated>

    <summary> Available on iTunesU or at its website. This is a recording of a University of California at Berkeley history course on the ancient Mediterranean given by Professor Isabelle Pafford during Fall 2007. There are 25 podcasts (each around one...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="podcasts" label="Podcasts" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> Available on <a href="http://deimos3.apple.com/WebObjects/Core.woa/Browse/berkeley.edu.1625336377">iTunesU</a> or at its <a href="http://webcast.berkeley.edu/course_details.php?seriesid=1906978476">website</a>.</p>

<p>This is a recording of a <a href="http://berkeley.edu/">University of California at Berkeley</a> history course on the ancient Mediterranean given by Professor Isabelle Pafford during Fall 2007. There are 25 podcasts (each around one hour, and 15 MB) starting with a couple on <a href="http://en.wikipedia.org/wiki/Ancient_Egypt">Ancient Egypt</a> and then passing through <a href="http://en.wikipedia.org/wiki/Ancient_Greece">Ancient Greece</a>, the <a href="http://en.wikipedia.org/wiki/Hellenistic_period">Hellenistic Period</a>, the <a href="http://en.wikipedia.org/wiki/Roman_Republic">Roman Republic</a> before ending with the <a href="http://en.wikipedia.org/wiki/Roman_Empire">Roman Empire's</a> collapse in the west around the 5th century <span class="caps">AD.</span> Most attention is paid to Greek and Roman history. A following course on <a href="http://en.wikipedia.org/wiki/Byzantine">Byzantine</a> history is mentioned, but I couldn't find it online.</p>

<p>As should be expected for a series covering so much, the lectures often quickly pass over topics. Some parts of lectures were lists of important events. Despite this, there were more than enough digressions onto engaging side-topics to maintain interest (for instance, there was a passage on the nude in Greek sculpture and another on the formal <a href="http://en.wikipedia.org/wiki/Cursus_honorum">political structure/progression in the Roman Republic</a>). Thus the podcasts serve as a good introduction to the breadth of ancient Mediterranean civilisations and highlights areas you may want to explore further (after this I was looking forward to learning more on the mid and late Roman republic). I can't find much fault with the content of the course considering its scope.</p>

<p>I can find fault with the production standards, which overall are frustratingly poor. The sound quality is often annoyingly bad. For one lecture I had the volume turned up to max and pushed the earplugs deeper into my ears and I still could barely hear the lecturer, who sounded like she was mumbling next to a static noise generator. Course administration comments are sometimes made during a lecture - including asking unintentionally rhetorical questions to what seem to be largely apathetic students. Considering these are lecture recordings I can understand this, but usually the first few minutes of each lecture are taken up with course administration too (these could have easily been cut). Also, Professor Pafford regularly refers to visual aides that are no longer available online (the bspace website mentioned in the podcasts has been shutdown). Also the first two lectures are missing.</p>

<p>A good introduction to classical history, made slightly less pleasurable by poor production.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Testing generated code</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2009/12/testing-generated-code.html" />
    <id>tag:www.cordinc.com,2009:/blog//1.83</id>

    <published>2009-12-07T19:50:46Z</published>
    <updated>2009-12-13T12:17:00Z</updated>

    <summary> What is the accepted way to test generated source code? A recent work project required me to generate some Java source code from small definition files as part of a larger framework. The plan was for other project teams...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="java" label="Java" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="technical" label="Technical" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p> What is the accepted way to test generated source code? A recent work project required me to generate some Java source code from small definition files as part of a larger framework. The plan was for other project teams to take the framework and use the generator to create source which would become part of their project. I wanted to write unit tests for the source code. The problem was how to write a test for code that didn't exist at the time the test was written because it hadn't been generated yet! I came up with a few options:  </p>


<ul>
<li>Do a text comparison between generated code and the previously created known text output of the generation process. If they are exactly the same, the test passes. This tests the generation process if correct but doesn't test the logic of the generated code. If the generated code has syntactic errors, compilers or <span class="caps">IDE</span>s will pick this up quite fast and the developers in the other project will complain quickly, but subtle logic could go unchecked for ages.</li>
<li>Write a test that generates a class file from known inputs then compiles it programmactically with the <a href="http://java.sun.com/javase/6/docs/api/javax/tools/JavaCompiler.html">Java Compiler <span class="caps">API</span></a> then loads the class into the <span class="caps">JVM </span>and runs tests against it. This would be better than the previous idea, as it tests the functionality of the result. This was my first choice solution. However, getting the Java Compiler <span class="caps">API </span>to work can be a bit hard. There was a paucity of documentation on this and in the end I couldn't get it to work within time constraints.</li>
<li>Generate the test at the same time as the generated code and pass them both to the other project. The other project would then test the generated code as if it was their code. This felt wrong to me. No other generations systems do this - it is like passing the buck. If there is an error in the generated code then the generator needs to be fixed not the generated class!</li>
<li>A 2-step process - test the functionality and generation process separately. First, create a class that should be the same as a generated class given known inputs (probably by generating it!) and write tests that work against that class. Thus the problem of testing not yet existing code is solved by using some code generated earlier. This tests the generated code's functionality as long as the generating process doesn't change. So the second part is to test the generation process hasn't changed using the first test in this list. Add another test to generate the code and check that it is exactly the same text as the class the rest of the test is written against. If the generation output changes then you have to modify the pre-generated class, and thus change the functionality test if required. Easy.</li>
</ul>

]]>
        
    </content>
</entry>

<entry>
    <title>CLCV 205: Introduction to Ancient Greek History</title>
    <link rel="alternate" type="text/html" href="http://www.cordinc.com/blog/2009/12/clcv-205-introduction-to-ancie.html" />
    <id>tag:www.cordinc.com,2009:/blog//1.82</id>

    <published>2009-12-02T20:26:13Z</published>
    <updated>2010-01-13T13:56:56Z</updated>

    <summary>Available on iTunesU with a course website. This complete university course (from Fall 2007) on Ancient Greek History from Yale is the best history podcast I have found so far. It consists of 24 lectures of about an hour&apos;s length...</summary>
    <author>
        <name>Charles</name>
        
    </author>
    
    <category term="history" label="History" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="podcasts" label="Podcasts" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.cordinc.com/blog/">
        <![CDATA[<p>Available on <a href="http://deimos3.apple.com/WebObjects/Core.woa/Browse/yale.edu.1899726321.01899726329">iTunesU</a> with a <a href="http://oyc.yale.edu/classics/introduction-to-ancient-greek-history/">course website</a>.</p>

<p>This complete university course (from Fall 2007) on Ancient Greek History from <a href="http://www.yale.edu/">Yale</a> is the best history podcast I have found so far. It consists of 24 lectures of about an hour's length each, all given by Professor <a href="http://en.wikipedia.org/wiki/Donald_Kagan">Donald Kagan</a>. It starts with an introduction to <a href="http://en.wikipedia.org/wiki/Mycenaean_Greece">Mycenaean Greece</a> before moving onto the <a href="http://en.wikipedia.org/wiki/Greek_Dark_Ages">Greek Dark Ages</a> and Homeric stories. The series ends with Philip of Macedon's victory at the <a href="http://en.wikipedia.org/wiki/Battle_of_Chaeronea_%28338_BC%29">Battle of Chaeronea</a> and the Greek Polis' permanent loss of independence. Along the way it details all the major events including: the rise and strangeness of Sparta; the rise of Athens and democracy;  Persian wars; and the slow decrease of power in the struggle for hegemony after the Peloponnesian War. Only the 27 years of the <a href="http://en.wikipedia.org/wiki/Peloponnesian_War">Peloponnesian War</a> seem to be under represented in coverage (from my previous knowledge of history). Despite 4 lectures being dedicated to it in the syllabus, most of these are taken by finishing prior topics and the buildup to the war. For the war itself, Professor Kagan suggests looking to other sources as it it too much to cover properly, and instead talks in detail about two related topics - <a href="http://en.wikipedia.org/wiki/Pericles">Pericles'</a> strategy and <a href="http://en.wikipedia.org/wiki/Thucydides">Thucydides'</a> history.</p>

<p>One thing I can't fault is the production. The podcasts are professional from start to finish. The only blemish is Professor Kagan's occasional coughing, but this is a minor issue. The podcasts are available in a number of formats on the course website: audio-only (the same mp3s that are on iTunes); video, in both high (around 700 MB) &amp; medium (around 250 MB) bandwith forms; and, complete text transcripts. The website also includes the notes handed out with each lecture, although these unfortunately are without the original images due to copyright problems. The website itself is downloadable too (albeit with only links to the audio and video files). While videos of the lectures are available, it is not really necessary to download them as they mainly just show Kagan talking at his podium. Rarely does he use any visual aid during the lectures. Thus these are excellent podcasts to listen to audio-only - very little will be missed.</p>

<p>The lectures are often a recitation of events together with discussion of how and why things may have occurred that way (for instance a section on various military strategies and whether they were correct). The aim appears to be getting the listener into the mindset of the ancient Greek statesmen (and thus the citystates in general). A goal largely achieved to my mind. There is less discourse on daily life (but still some). Professor Kagan also talks a little about historical controversies and often compares ancient events to modern history (in particular around the use of military force). In both situations he tends to declare his own prejudices so the listener is not led too much.</p>

<p>This is a highly recommended lecture series - interesting content that goes into the subject with some depth and so well produced it is surprisingly easy listening.</p>]]>
        
    </content>
</entry>

</feed>
