Monday, January 25, 2010
Are you going to the wedding?
Saturday, January 23, 2010
Saturday, January 02, 2010
Panorama of Douglas Bay
This is a panorama of Douglas Bay, Isle of Man. I took it from the end of the Victoria Pier, and the Tower of Refuge just nicely fell into the center of the image.Wednesday, December 30, 2009
Security Theatre
Often, this "something" is directly related to the details of a recent event. We confiscate liquids, screen shoes, and ban box cutters on airplanes. We tell people they can't use an airplane restroom in the last 90 minutes of an international flight. But it's not the target and tactics of the last attack that are important, but the next attack. These measures are only effective if we happen to guess what the next terrorists are planning.Of course, the result of this 'magical thinking' is also the terrible changes that are taking place to the due process of criminal proceedings at law. The introduction of arbitrary periods of detention without charge, the holding of terrorism-related trials in camera, the rhetoric of hatred of any other political or cultural outlook than our own... this is dangerous stuff that just serves to increase the threat from those opposed to our way of life. Back to Bruce:
If we spend billions defending our rail systems, and the terrorists bomb a shopping mall instead, we've wasted our money. If we concentrate airport security on screening shoes and confiscating liquids, and the terrorists hide explosives in their brassieres and use solids, we've wasted our money. Terrorists don't care what they blow up and it shouldn't be our goal merely to force the terrorists to make a minor change in their tactics or targets.
Our current response to terrorism is a form of "magical thinking." It relies on the idea that we can somehow make ourselves safer by protecting against what the terrorists happened to do last time.
Despite fearful rhetoric to the contrary, terrorism is not a transcendent threat. A terrorist attack cannot possibly destroy a country's way of life; it's only our reaction to that attack that can do that kind of damage. The more we undermine our own laws, the more we convert our buildings into fortresses, the more we reduce the freedoms and liberties at the foundation of our societies, the more we're doing the terrorists' job for them.So, when you're thinking about who to vote for in future (in the UK general election, for example), why not challenge them to stop the damage that's being done to our relatively free way of life, pull back from culturally aggressive stance in international politics, and stop stoking the flames of the conflicts that spawn terrorist acts.
p.s. on the 'voice of the people', it appears the ‘newspapers’ are being deemed to be the ‘voice of the people’ in that mad country, the (dis-)United Kingdom, so a populist, theatrical, approach to security is the inevitable outcome. Of course, it is the broadcast & newsprint media that treat said ‘newspapers’ as ‘the voice’, in addition to their weak lackeys in Westminster. It’s a vicious circle of bullying and subservience maintained by those with the loudest voices, the deepest pockets and the least integrity.
Monday, December 28, 2009
Camera Update
Sunday, December 27, 2009
Copenhagen Summit on Climate Change
If China railroaded Copenhagen then isn’t it time those of us in Western nations stopped filling our Christmas stockings with cheap Chinese goodies whilst ignoring its those very actions that drive China to want to exhaust its ‘fair share’ of the ‘Industrial Revolution’. We may not have power over our leaders or Copenhagen, but Western buyers do have pocket power without which they can let China know what they think about ethics. Think about that next time you reach for your credit card for that latest gadget. Which regime are you supporting.I guess this is the small-scale, personal approach to implementing the strategy I suggested above.
Monday, November 23, 2009
Photos
Tuesday, September 01, 2009
Obligatory 9/11 post
Monday, August 31, 2009
Alan Turing Petition
Saturday, August 08, 2009
The Monomyth vs. the Automyth
- people: farm boy, new advertising executive, grizzled mountain man, washed out detective
- places: Alabama USA, the Shire (or an analogue of), a moon-base, a small shop in London
- challenges: alien invasion, disease, death of a parent, financial ruin (personal or global)
- monsters: the boss, an out-of-control robot, the Devil, the judge(s)
- assistants: the girlfriend, the grand-parent, the old mage, the bestest buddy, the advocate
- ... and so on
Thursday, August 06, 2009
VirtualBox on Windows Hosts
Andy, you might want to be careful about using a dynamically expanding disc file for your root file system. NTFS is notorious for fragmenting files as they grow - especially if your file is living on a partition with other activity. And as we all know, the more fragmented a file gets, the poorer the performance becomes as the disc heads have to seek across more and more diverse areas of the disc to get to the content of the file. Where you have a virtual file system in a file, this is only going to get worse, because the file system you have inside the file will have no knowledge of how the data is distributed over the real disc, so it can't make any decisions over data distribution within the file system that have any meaning on the disc platters.
Thursday, July 16, 2009
Logging out with HTTP Basic Authentication
There is a downside to this arrangement, and that is that HTTP BASIC authentication doesn't really support the concept of logging out!
As normal with a Java web application, the logout operation is a matter of invalidating the current HttpSession, throwing away any cached user configuration, and redirecting the user to a 'you are logged out' page. This can be achieved by having a filter or a servlet pick up the 'logout' request, mark the HttpSession associated with the current HttpRequest object, and deleting the JSESSION cookie that identified the session. The response then just needs to contain a logout message, or redirect, or whatever you desire for your site.
That's all well and good if it's just the web application involved. However, in our scenario, we have web server to consider too. As it stands, there's nothing in the HyperText Transfer Protocol ('HTTP' to you and me) that allows the web application to tell the web server that the HttpSession is over - the application doesn't talk to the server, so (according to almost all the web sites I could find with Google) there's no way to tell the server to invalidate it's knowledge of the end user and their credentials.
Or is there....
The key factor is that it is possible to make the server re-challenge the user for their credentials in the same way as they were when they started using the application, and this can be made to have the same effect as logging them out. Note that the critical fact that previous web-pages on this subject seem to have missed is that HTTP BASIC authentication has a realm parameter.
By knowing what the realm is that the web-server used to the authenticate the user, we can cause the browser to re-authenticate against that same realm, by challenging the browser with an HTTP 401 (just like the web-server does).
The process (in my application) works like this:
- The user clicks the logout link to go to /logout.html, which tells the user they are being logged out. This is a nice-to-have page to make this process a little more friendly, you could skip it and go straight to the next step
- The browser pauses for 1 second on this page, then redirects to /logout
- This url is mapped to a logout filter, which does the normal session termination activities I mentioned above. But in order for the next step to work, the filter also registers the current HttpSession key with the LoggedOutServlet (storing it in a singleton HashSet of keys), and creates a has-logged-out cookie with the HttpSession key as the value of the cookie.
- The logoutFilter then redirects to /loggedout which has been mapped to the LoggedOutServlet in my web.xml:
- The LoggedOutServlet looks for the has-logged-out cookie. If cookie exists, and the value is in the servlet's register of logging-out keys, then the key is removed from the register, the cookie marked as deleted, and an Unauthorised (HTTP 401) response is returned to the user:
public void setupResponseForLogout(HttpServletResponse response) { response.setStatus(HttpServletResponse.SC_ UNAUTHORIZED); // HTTP 401 response.setHeader("WWW- Authenticate", "Basic realm=\"xyzzy\""); } - The user is then prompted by the browser to re-authenticate. The critical thing here is that the realm (set to 'xyzzy' above) is set correctly in the response. If this is done, then the web-server (which must be authenticating with the same realm) will correctly re-authenticate the user if they try to login again. So the consequence is that the user is effectively logged out, and cannot get back into the application without being challenged for their credentials again. This works because the browser has been asked to authenticate against a specific realm, so that will be used in the authentication process, and will force the web server to full re-check the user's credentials - refusing access if they get it wrong.
<servlet>
<description>Logout Servlet</description>
<display-name>LoggedOutServlet</display-name>
<servlet-name>loggedout</servlet-name>
<servlet-class>
com.xyzzy.web.LoggedOutServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loggedout</servlet-name>
<url-pattern>/loggedout</url-pattern>
</servlet-mapping>
Wednesday, July 01, 2009
TreeSet and implementing the Comparator interface
My experience of Collections thus far has taught me that most of them are built upon detecting object equality through the equals() and hashcode() implementation in your class. See my earlier post and the posts of Andy Beacock referenced therein. However, today I ran into problems with objects vanishing in a TreeSet.
Back to the requirements first. I have list of Bank Account objects I wish to show on a web-form, but that list should also be modifiable by the user with an Add Form, and a Remove button on each listed account. So far so good. One more thing, the list has got to be in account name order on display. For this example, a Bank Account consists of a pseudo-primary key (id), a Bank Name, an Account Name, an Account Number, and a Sort Code. The id is not shown, and the records are unique by Account Number and Sort Code (and therefore implicitly by Bank Name).
Obviously, Bank Names should should not really be store in a Bank Account record - they should be stored separately and referenced by foreign key, as indeed, should Sort Codes - in fact, in an ideal world, the Bank Account record would be an id, a name, an account number and a foreign key to a branch as identified by the sort code. However, you know as well as I do that this is not an ideal world, and most of the time, we have to deal with the world as we come to it.
So, back to my slightly contrived example. I'm going to ignore completely all the contextual information about display technology, form interaction, transactions, etc., and concentrate on the core issue: SortedSets are nasty wee buggers!
There are two ways to manage the display of sorted data: sort on insert, and sort on display. If you're displaying often, and inserting & deleting infrequently (as in this example), sort on insert is preferable, otherwise you spend a lot of time sorting your data again and again with no change to the data.
Having looked at the implementations of the SortedSet interface, we really only have one available in the Java SDK (I'm staying away from the Apache Collections for now), and that is TreeSet, for which you specify a Comparator at construction time. Naively, I assumed that my comparator would just be interested in the Account Name - that's the field by which I wish to sort, after all.
@Override
public int compare(BankAccount o1, BankAccount o2) {
return o1.getAccountName().compareTo(o2.getAccountName());
}
(I'm leaving out the normal defensive programming and exception handling for clarity)
However, my BankAccount class implements equals() and hashcode() as normal, with the sortcode and the account number - these being the 'business key' if you like. So, on this basis, I expected TreeSet to sort on name, and use equals() and/or hashcode() to determine whether the Set contains a given BankAccount on insertion - in the same way that HashSet would.
Ooops, no.
Turns out that TreeSet doesn't use equals() or hashcode() at all. It uses the Comparator for sorting and contains() checking. So now, my Comparator implementation looks like this:
@Override
public int compare(BankAccount o1, BankAccount o2) {
int result = o1.getAccountName().compareTo(o2.getAccountName());
if (result == 0) {
result = o1.getSortCode().compareTo(o2.getSortCode());
}
if (result == 0) {
result = o1.getAccountNumber().compareTo(o2.getAccountNumber());
}
return result;
}
Now I have data sorted on insert and display, and the data doesn't get lost if someone enters two accounts with the same Account Name.
In conclusion, I think that the only reason this gotcha got me was that I was motivated to use the TreeSet simply by the requirement to sort by name, so I wrote the Comparator with only that in mind. A correct implementation of really should include the business keys of the entity under consideration... of course, I'd just done that, I might have had even more trouble with the sort-by-name requirement (i.e. a non-key property).
Friday, June 19, 2009
I want one...
Thursday, June 18, 2009
HashCodeBuilder is great, but ...
When doing domain modelling, one of the important things to get right is the definition of the equals() and hashcode() methods. I'm going to use a class that's used to represent a compound primary key in a Spring/JPA/Hibernate environment. The PaymentMethodId class has an owner, and two currency codes - one for the source of funds, and one for the destination of the funds, to allow for currency conversations between the two.
@Embeddable
public class PaymentMethodId extends CompositeId {
@Column
private Integer ownerNumber;
@Column
private String sourceCurrencyCode;
@Column
private String paymentCurrencyCode;
/**
* Compare unique business key (number, source code and payment code)
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || !(other instanceof PaymentMethodId)) {
return false;
}
PaymentMethodId paymentMethodId = (PaymentMethodId) other;
return ((this.ownerNumber == null ? paymentMethodId.ownerNumber == null
: this.ownerNumber.equals(paymentMethodId.ownerNumber))
&& (this.paymentCurrencyCode == null ? paymentMethodId.paymentCurrencyCode == null
: this.paymentCurrencyCode.equals(paymentMethodId.paymentCurrencyCode))
&& (this.sourceCurrencyCode == null ? paymentMethodId.sourceCurrencyCode == null
: this.sourceCurrencyCode.equals(paymentMethodId.sourceCurrencyCode))
);
}
@Override
public int hashCode() {
int result = 13;
result = (ownerNumber != null ? 19 * result + ownerNumber : result);
result = (paymentCurrencyCode != null ? 19 * result + paymentCurrencyCode.hashCode() : result);
result = (sourceCurrencyCode != null ? 19 * result + sourceCurrencyCode.hashCode() : result);
return result;
}
}
I've left out constructors and getters and setters as these should be obvious.
As you can see, I like to make use of the 'trinary if' expression for brevity. Just imagine how much more complex these methods would be if written out in full!
Anyway, similar to Andy Beacock's post on this subject, we can firstly simplify the above as follows:
@Override
public boolean equals(Object obj) {
if (obj instanceof PaymentMethodId) {
PaymentMethodId other = (PaymentMethodId) obj;
EqualsBuilder builder = new EqualsBuilder();
builder.append(getOwnerNumber(), other.getOwnerNumber());
builder.append(getSourceCurrencyCode(), other.getSourceCurrencyCode());
builder.append(getPaymentCurrencyCode(), other.getPaymentCurrencyCode());
return builder.isEquals();
}
return false;
}
@Override
public int hashCode() {
HashCodeBuilder builder = new HashCodeBuilder();
builder.append(getBrokerNumber());
builder.append(getSourceCurrencyCode());
builder.append(getPaymentCurrencyCode());
return builder.toHashCode();
}
Note the use of getters instead of properties - as Andy mentioned.
However, the important bit that really is the reason for this post is the last line:
return builder.toHashCode();
It is vital that you don't write:
return builder.hashCode();
Notice the subtle difference? The hashCode() of the builder itself is worse than useful as it will vary every time the method is run, so any Hash-based collection code will find your object has a different hashCode, every time it asks, risking the integrity of the data.
Thursday, May 07, 2009
The "Two Source" rule?
Okay, guilty as charged, I've only used one source, slashdot.org, but then I'm only a blogger so I don't count because my writing is too risky anyway.
Wednesday, May 06, 2009
Alexander Mosley, RIP
Friday, April 03, 2009
Once more with feeling...
Wednesday, March 18, 2009
Knife Crime in London
Voyage
Originally posted at GameBoomers:
What is it?
I was a young boy, just striking out on my own path at the town library when I first came across Jules Verne. My introduction to the French man's works of speculative fiction (as sci-fi used to be known) came in the form of the Journey to the Centre of the Earth. I loved it; I still do. There is one difficulty with Verne's work, however. It's all written in French, and so every time I read his work, it is through the filter of a translator's pen. This shows up in Journey to the Centre of the Earth in the fact that there are two main translations of the book, and they're completely different. The main character in one of the versions is a completely different man, in name as well as character, from in the other.
So it seems than game developers seem to like following in this tradition of 're-interpretation' rather than translation. In particular, the recent “Journey to the Centre of the Earth” and “Return to
Well, the answer is that they've done the same as they did with their first game - Voyage is a Verne-esque telling of a story that starts with an idea that he had. This is not to say that the result is somehow 'wrong', it would simply be a mistake to say that Kheops have told Verne’s story verbatim.
What we have instead is a nonlinear, point-n-click, mostly pre-rendered 360° bubble-based adventure game telling the story of Michel Ardan, a wild-hair, moustachioed 19th century French explorer, and his journey to the Moon. And, yes, he actually reaches the Moon, where Verne's characters did not.
Is there a plot?
The game begins with our hero, Michel Ardan, waking up in a bullet-like space capsule in the company of Barbicane and Nicholl - his fellow space explorers, after the violent launch of the capsule towards the Moon. However, he soon discovers that all has not gone well since the launch.
As I've already made it clear that Michel reaches the Moon, I think it fair to also mention that he also encounters intelligent life there. The backbone of the story is Michel's encounters with the Selenites, (from the Greek 'seleno', being the Moon) and his efforts to return to the Earth. Along the way he discovers some of the story of the Selenite civilisation and their relationship with Earth. And, of course, there are plenty of puzzles along the way, but then it wouldn’t be much of an adventure game without them.
Notable Features
In this highly puzzle-oriented game, the puzzles are pretty varied. Some involve the decipherment of the Selenitic written and spoken language – a tuneful thing that’s not as hard as it sounds; a fair few puzzles involve combinations of inventory items, some are mathematical in nature, some mechanical, and some are just pure logic. A number of the over-arching goals can be achieved through a variety of means. This is the source of much of the game’s nonlinearity. If you get stuck somewhere, you can often make progress in other parts of the game before coming back to the sticking point.
In addition, there are a number of optional side puzzles that aren’t essential to your progress towards home, but which reveal some extra facet of lunar life. From roughly halfway through the game (at least as I played it), you gain a small ‘helper’. The ‘helper’ is there to reveal information, clues and your score. Certain puzzles require you to have achieved a specific number of points before you can obtain information or inventory items. However, obtaining sufficient points is again possible in a variety of ways. Solving parts of the Selenitic language, or deciphering mathematical puzzles or manufacturing chemical substances using the Selenitic machines all improve your score.
Ardan automatically keeps a comprehensive log of his experiences. This includes some of the conversations, the details of his investigations as to what happened in the space capsule before he woke, and a number of key diagrams regarding his objectives later in the game.
A notable pair of features in this point-n-click adventure is the inclusion of a small number of timed sequences early in the game, followed by some hand-eye-coordination-based jumping puzzles. Unfortunately, these puzzles all result, upon failure, in the death of Ardan, but he is always resurrected to a point immediately before the timed sequence or jump began, so there’s no real penalty in failure, other than a certain gathering frustration. On the plus side, once each jump has been successfully performed, Ardan will be able to repeat them without the player having to beat the puzzle again. I found these a minor irritation rather than a serious problem.
Graphically, the experience of Voyage is colourful and imaginative. With our modern knowledge of the Moon, we would expect the palette of this game to be rather dull and leaden, but Kheops Studios clearly know better, with good texturing, a rich palette of colours, refined animation, and very detailed modelling.
Most of the audio in the game is top quality. The music is unobtrusive, but appropriately used to set the mood at various stages of the game. The voice acting of the Selenites is excellent – I particularly enjoyed their native voices, which are rather harmonious. The English voice acting was good, with the exception of Ardan himself, whose narration and accent I found jarred slightly. I think he was supposed to sound like an educated Frenchman speaking English – presumably he sounds better in the French version – but in English he came across as stilted and slightly manic at the same time.
Any other novelties?
Not having completed a Kheops Studios’ game before, I didn’t realise quite how much they like inventory combining puzzles. However, to their credit, the required combinations aren’t extraordinarily illogical, though some are surprising. A nice feature here is the pictorial log that is kept of all the successful combinations you’ve made throughout the game – this simplifies the task of re-creating earlier combinations later in the game.
An intriguing novelty in Voyage is the requirement that you don’t just have to click on a button to make the machines work, you have to understand what those machines are going to do. A number of the machines will ‘work’ by you pressing buttons, but will only do the ‘right’ thing when you understand them properly.
There are at least three puzzles that can be attempted several times, to a number of standards – in each case, the lowest standard is sufficient to ‘solve’ the puzzle, but you can significantly improve your overall score by achieving the higher levels. A feature here that is rather useful is that if you find that you’re weak in one puzzle – perhaps figuring out the Selenitic mathematics defeats you – you may well be able to make up for it with the sounds of the their spoken language.
Oddities
Now we reach the only really odd thing about this game. Although there are five profiles under which you can save your game, you must select your profile during level 1 of the game – however, there’s no warning as to when level 1 ends, so no indication when you should choose your profile. The manual states that level 1 is the capsule level, but it’s not clear whilst you’re playing the game when this level ends. So, I suggest that anyone playing this game saves their first game immediately the first cut-scene ends – thereby choosing a profile and eliminating any risk of getting caught out like I did.
Of course, if you’re not sharing your computer with other people, this oddity problem won’t even affect you, but it did me, so I choose to mention it.
Conclusions
This was an enjoyable telling of a Verne-inspired tale, though I’ve found it helpful to ignore the connection with Monsieur Verne in the long run. I would certainly play another game by Kheops Studios. So, to summarise: a point-n-click adventure, featuring a good story, some hand-eye coordination, a few timed sequences, plenty of opportunities to die, but with immediate resurrection to before the fateful decision was made, unlimited saves, but an odd profiling system, a variety of logical, mathematical, inventory, linguistic and mechanical puzzles, one musical puzzle, and no slider puzzles, nor mazes.
From a technical standpoint, there were very few graphical bugs, nor audio glitches, except during the final cut-scene, which was a shame, as it concludes with a nice little twist to the story. The game has no patches, and no serious crashes.
So, all in all, a good game, but not spectacular, hence the final grade.
Grade: B
What do you need to play it?
Minimum Requirements
· OS: Windows® 98SE/ME/2000/XP
· CPU: 800 MHz Pentium® III
· RAM: 64 MB
· CD-ROM/DVD-ROM: 16X Speed
· Video: 64 MB DirectX® 9 Compliant Video Card
· Sound: DirectX® 9 Compatible
· Input: Keyboard, Mouse and Speakers
Recommended Requirements
· OS: Windows® XP
· CPU: 1 GHz Pentium® 4
· RAM: 128 MB
· CD-ROM/DVD-ROM: 24X Speed
· Video: 64 MB DirectX® 9 Compliant Video Card
· Sound: DirectX® 9 Compatible
· Input: Keyboard, Mouse and Speakers

