Three-car pileup whilst waiting in traffic…

SANY0056I was involved in my first car accident as a driver last week. It was a bit of a shock, and I’m glad to say that no-one was hurt and the car wasn’t too badly damaged. I was in traffic, sat waiting behind a car that wanted to change into a very busy lane. The car behind me didn’t want to wait, and tried to move around on the other side… as another car came up behind it and smashed it’s front as it came out. It was pushed into my car, at the back.

Luckily, Jen and Freddy weren’t in the car (I was on my way to pick Fred up from nursery) and my passenger (Jen’s Dad) was fine, and took control for me. I was a bit too shocked at first to know what to do.

I certainly wasn’t expecting that to happen sitting still, and obviously the insurance companies have agreed that it’s not my fault. One of the other parties is offering to have us repaired free of charge (with a free courtesy car) at one of their approved repairers, without touching our no-claims bonus or paying the excess or any of that. The car’s booked in to be seen this week, and probably repaired the week after. Having seen the damage in the light now, it’s not too bad and should fix up nicely (fingers crossed!)

I wasn’t actually looking behind me just before the crash to see if one car pulled out inadvisably, or the other car was driving too fast, or any of that. But it’s nothing I could have done anything about it – except possibly try to go around the car blocking my lane myself, in which case I’d have been hit, my car would have been a write-off (the front of the car was mashed completely, spread across the road), and I might not be quite so happy to get back into the driving seat!

Learning Unit Testing VII – Running and Redesigning

I can see this page 10 being a pretty big thorn in my side. After stating fairly clearly

models can move up to their move rate

under the ‘Moving’ heading, it then says

A running fighter can move at double speed: 8″ rather than 4″, for example.

This is going to have a fairly large impact on the tests involved. The test for exceeding total movement (both in one and two moves) will only throw an exception if the total movement is double the model’s Movement rate now. In addition, a new test is going to have to be added to ensure that moving over the Movement rate sets an ‘IsRunning’ flag to true. The first test to add would be one that allows a model to move more than it’s Movement rate, but sets the IsRunning flag.

[TestMethod]
public void MoveModel_MovesDistanceOverMovementRateAndSetsIsRunningFlag()
{
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
testModel.MoveModel(newX, newY, newZ);
Assert.IsTrue(testModel.IsRunning);
}

Even with the correct code added to MoveModel –

if (this.TotalDistanceMoved > this.Movement)
{
this.IsRunning = true;
}

– this doesn’t work. Because ValidateMove is throwing an exception (as we designed in earlier). So ValidateMove has to allow up to twice the MovementRate.

if (GetDistanceFrom(positionX, positionY, positionZ) + this.TotalDistanceMoved > this.Movement * 2)
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}

Now, all the tests pass. But should they be? Checking my working, the MoveModel_CannotMoveFurtherThanModelsMovement test is moving the model more than twice it’s movement rate. So it is correct to throw an exception, and therefore pass the test. Anything testing to stay beneath the model’s Movement rate is obviously going to be beneath it’s doubled Movement rate, so they will continue to pass. MoveModel_TotalMovementInASingleTurn… that tests whether two movements that combined make more than the model’s Movement is also working correctly. But I’ve noticed I had an error in that test:

[TestMethod]
public void MoveModel_TotalMovementInASingleTurnCannotExceedModelMovement_ThrowsArgumentException()
{
bool correctExceptionThrown = false;
try
{
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
testModel.MoveModel(newX, newY, newZ);
testModel.MoveModel(0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

The try catch was working on both MoveModel calls – and those values (after the calculation fix a couple of posts back) would have sent it way over the Movement on the first move, not the second. Moving the try…catch so that it only covers the second call to MoveModel would check that it’s failing in precisely the right place. By reversing my change to ValidateMove, I can confirm that the test would have failed before if the try…catch was in the right place. Putting it back in, and it throws an exception on the second MoveModel call, just as it should do. All the tests pass, and I’m a little more comfortable about them testing the right thing.

Lesson learned: Only test exactly the line you expect to break things.

The rest of the ‘Running’ section mentions not being able to shoot – this is something that we can cover in the Shooting section (after Movement), and isn’t important right now. The next bit that should matter is that a running model must stop 8 units away from an enemy model that he can see. This brings a number of things into play immediately:

  1. Can we identify models as being enemies?
  2. Can we identify which models can see others?
  3. How do we perform the sight checks all along it’s movement to work out if it can see the enemy (they may not be in sight at the beginning of the move, only halfway along it)?
  4. What action should be taken if the model’s movement is disrupted – should it still count as running? How can it be prevented from moving further?

Before we write tests, we should explore the problem a bit further.

Essentially, the enemy is at the centre of a circle 16 units in diameter (radius of 8). The active model’s path may intersect the circle at some point. If it does so, the active model must stop at the point along that path nearest to his starting point, providing that he can draw a line of sight to the enemy model at the centre of the circle.

So we only really need to work out if any point of the active model’s path intersects the enemy ‘disruption’ circles, and check those sections of the path for line-of-sight to the centre of the circle.

IE9 Beta + VS2010, and a blog-reading tip

I’ve been experimenting with IE9 beta in work recently, and been finding it annoying when I go to show someone what I’ve been working on and need to refresh a page a couple of times after running it from Visual Studio 2010 before it ‘takes’, and will display the page and work properly. I’m getting a little tired of saying ‘it’s only a beta…’ and sort of harms my decision to install it in the first place. Sure, hitting refresh a few times isn’t really cutting into my productivity any but it’s one of those small frustrations… something about controlling one’s environment, and smoothing our day’s problems out. That sort of thing.

I was browsing around trying to find help on a problem I’ve been working on at home (another learning project), and came across a blog that had a great explanation, a working sample, and the answer that I wanted – although the explanation didn’t point me to the answer that I wanted, when I went back and re-read it I realised it was right there and could have solved my problem an evening sooner. D’oh.

One of my habits when reading blogs is that if I find the post useful, or at least well-written and informative, I will go to the front page and see what they’ve posted recently. Dan Wahlin’s blog front page is an archive page, so you get to see a lot of interesting titles all at once. One of those titles was Getting the IE9 Beta to Play Well with Visual Studio 2010 and it described exactly the problem that I’m having in work with the beta, and also a suggestion to get around it. Since I found this in the middle of the Christmas bank holiday season, I had to wait a few days to try it out and see if it works… I’m not really keen on installing IE9 at home just to see a few days earlier! It seems to have worked so far, it’s a lot nicer than hitting refresh over and over till it sticks. So anyway, if you see a helpful or interesting blog post – look up recent posts in that blog. There might be something useful there too.

2010

As promised last year, I’m going to try and post a review of the past year on the first day of the new year. This is how 2010 shapes up for me (see 2009 here).

Did you enjoy this year?
I did, quite a lot! Freddy stayed out of hospital almost the entire year, only visited a tiny bit for a double-check – and it turned out to be exactly what the GP had suggested.

What did you do in 2010 that you’d never done before?
Played RuneQuest, drove a car without an instructor in it (ooh!), drove on a motorway, made new year’s resolutions, went on a medieval re-enactment weekend.

Did you keep your new year’s resolutions, and will you make more for next year?
I kept some. I proved (to myself, at least) that the secret is to have a plan of action, not just a goal. Goals don’t meet themselves. So my resolutions then (described in full here):

  1. Filing
    Done! This had a weekly target to meet, and I made myself ‘catch-up’ if I got behind any week. This is by far the most successful of my resolutions.
  2. Dark Elves
    I set vague targets that I never really tried to meet. Hence, I had to re-evaluate what I could realistically do, and toned down from ‘paint everything’ to ‘paint the Corsairs’, which itself isn’t complete (but is very very close!)
  3. Driving Licence
    In the eleventh hour, I completed this one! I passed at the beginning of December, after failing twice this year (and once last year). Finally, a driver.
  4. German
    I always planned to do this once I’d cleared a couple of other things off my list. I never cleared enough space in my week to do it.
  5. Star Trek Cards
    Done! Selling things just means you have to do something, and get organised to do it. I very much enjoy the television I bought with the proceeds, too!
  6. Family Tree
    There’s still a little more to find out (I need to confirm my records dive, after all) from grandparents, but I feel good about the progress on this one. Even though it can never really be called ‘finished’.
  7. Wargame Tools
    Scrapped. Abandoned. Lost my motivation, and quit.

So ones to take on to next year – Dark Elves, Learn German, Research Family Tree. I’ll try to make a more definite plan on those later, so I can make more meaningful progress this year.

Did anyone close to you give birth?
Not this year, although a lot of people got pregnant – four of my cousins, and we’re expecting again!

Did anyone close to you die?
I think I am a lucky charm – everyone’s still with me!

What countries did you visit?
None. The furthest afield I went this year was London, twice. Portsmouth a couple of times. Nowhere more exciting than that.

What would you like to have in 2011 that you lacked in 2010?
I’m not sure of anything I lacked in 2010 in particular… maybe the time to go out and see people a bit more? A foreign holiday – I’ve not been more than a hundred miles from home in over two years now!

What date from 2010 will remain etched upon your memory, and why?
December 2nd, passed my driving test. December 1st, saw our new baby on the scan for the first time.

What was your biggest achievement of the year?
Passing the driving test. Learning to paint ‘wet blending’ style.

What was your biggest failure?
Failed to keep some of my resolutions. Failed two driving tests. Not sure which is bigger, I think I’ve had an OK year, failure-wise.

Did you suffer illness or injury?
Only a small bit of illness, and in general a very healthy year.

Did you have to go to the hospital?
Only once, to get Freddy checked. It turned out to be exactly what the GP thought it would be.

What was the best thing you bought?
The new television – 42 inch LCD Full HD oh yeah! Second place would be the car – quite lucky, that one.

Whose behaviour merited celebration?
Freddy, for being absolutely wonderful.

Whose behaviour made you appalled and depressed?
The Pope.

Where did most of your money go?
Ignoring mortgage payments, it’d be on the car and the car insurance. Less said about that the better.

What did you get really, really, really excited about?
Everything Freddy does – running around pretending to be a dinosaur, learning his animals, he’s fantastic. Also, about getting ahead with my family tree stuff, that felt pretty rewarding.

What song will always remind you of 2010?
Probably something by Katy Perry. She has a really annoying -uwuh-uh-o sort of sound, it doesn’t sound very nice at all. But sticks in the head. Hopefully, it’ll end up being Candyman (thanks to Chris Evans for playing it every Friday morning on BBC Radio 2, it’s a nice song!)

Compared to this time last year, are you:
i. Happier or sadder?

About the same. I was pretty happy last year, and I’m doing well keeping it that way!
ii. richer or poorer?
Almost definitely richer. More monthly expenses (I got grown up, and did life insurance, pensions, and of course the car now) but at least I’ve saved up a bit since buying the house!

What do you wish you’d done more of?
Gaming. Not enough games this year by far.

What do you wish you’d done less of?
I don’t really know. I’ve done a lot more grown-up things than I have in the past, but I don’t know about doing less of them… for the most part, it’s all done and won’t need doing again for a long time!

How did you spend Christmas?
At home, doing almost nothing. We had a few visitors, Freddy opened everyone’s presents, and had a really great time. As I write this, I’m awaiting a second Christmas with my family visiting me (2nd January), because the snow prevented them coming up the weekend we’d originally planned.

Where did you ring in 2010?
We had an uneventful night, went to bed then realised “Hey, it’s midnight!”. Then I heard people outside so I ran out and joined about half-a-dozen neighbours banging saucepans.

What was your favourite TV programme?
We’ve been indoctrinated into The Big Bang Theory and Firefly, both due to major nagging. Both were really good shows! We also finally got onto Deep Space Nine on DVD, I can’t wait to get a bit further with that one.

Do you hate anyone now that you didn’t hate this time last year?
I’ve got a nasty feeling that as I’ve learned more about the Pope, I hate him more. Which is a bit disconcerting.

What was the best book you read?
I re-read a lot of old favourites. I finally got a box of books back from my parent’s loft, I’m looking forward to getting through some of those. I didn’t read many new books, and the only one I remember liking was Brave New World. But that was a good one!

What was your greatest musical discovery?
This year, I discovered… nothing. Not a specific band, anyway. My musical discovery will probably be the chance tuning in to Jack FM, a local station that ‘plays what we want’. It also has some hilarious one-liners between songs – “If we agreed with you, we’d both be wrong. That’s why we play what we want.” and “On Jack FM, we mostly play what we want. Sometimes, we play what we feel like instead.” A lot of the old stuff, like Blondie, Supertramp, Pulp, Oasis, Blur, The Lightning Seeds, and a whole load I don’t even know the names of. A whole mix, right back to the 70s.

What did you want and get?
A driving licence, and we’re expecting a new baby!

What did you want and not get?
More of my new year’s resolutions complete.

How did you earn your keep?
Still programming. Still loving it. I funded a new television by selling off my old Star Trek cards. End of an era.

What was your favourite film of this year?
Scott Pilgrim vs. The World. That’s definitely my cup of tea! I missed a lot of films that I wanted to see, but maybe I’ll catch them on DVD next year. Iron Man 2 was also pretty good, but Scott Pilgrim just got me right there, you know?

What did you do on your birthday, and how old were you?
I was twenty-six, and I can’t remember a thing about it. Honestly. I think I bought the telly? I seem to have had a two-month blogging blackout over the summer. I have a feeling I failed a driving test around then.

What one thing would have made your year immeasurably more satisfying?
Doing something memorable with the birthday! I think my year has been pretty good. Maybe passing the driving test earlier would have been good? We’d probably have missed the awesome deal we got with the car though.

How would you describe your personal fashion concept in 2010?
“They still fit, I’ll still wear them.” I might need to get something new soon though.

What kept you sane?
Freddy – he’s adorable.

What political issue stirred you the most?
The Pope’s state visit to this island. Enough to get me involved in my very first protest. That was a bit surreal.

Who was the best new person you met?
Mostly, I’ve only met people through work or through Freddy’s nursery. I think I might need to get out more.

Tell us a valuable life lesson you learned in 2010:
Toddlers will repeat anything you say to them.

Quote a song lyric that sums up your year:
I can’t remember the words, but I remember a Weetabix commercial which featured a driving examiner’s lament, to the tune of I Will Survive. That’s probably apt, in the circumstances!

*** BONUS QUESTIONS (thanks Lone Cow!) ***

What is the best thing that you were given?
I was given a revised salary in a ‘department restructure’ at the beginning of the year. After last year’s pay review, half the team left and the other half were looking for work – made for a powerful bargaining position. Yeah, I’m a greedy bastard at heart.

What is the best thing you have given someone?
I gave Freddy this toy kitchen, which he absolutely adores. I gave Jen a car. I shared my baby with the world!

Thanks everyone! That’s it till next year!

Unimaginative film posters

I saw a poster on the side of a bus the other day, advertising the film London Boulevard. I thought it looked a bit familiar…

It’s almost identical to the poster for Quantum of Solace.

Quantum_of_Solace_onesheet

Man standing protectively in front of woman, looking in different directions, no background details, gun held casually by the side, little or no facial expressions…

I get the feeling I’ve seen this poster for many other films too, I just can’t place it at the moment.

Back on the Wagon

My gaming has been suffering recently. I’ve definitely been on target with “spend less” – although the temptation to grab a new rulebook or two has been pretty strong, I’ve managed to avoid it. Unfortunately, real life has been getting in the way of getting any actual gaming done – I’m busy, my gaming group is busy, no-one ever lines up a day together. I have, however, used a few days off of work to get ahead on my Dark Elf painting.

The particular style of batch-painting that I favour is ‘do every model at once’, meaning that my current batch is about 60 Corsairs. The downside to this is that until you pick up a model and examine it, as I did this week, it becomes difficult to work out how far away you are from completing. I’m just about entering the final detail stage, which for me means that I’ll be dividing models up into groups of ‘haves’ and ‘have-nots’ for particular things. The first will probably be gemstones – every model with a gemstone goes in one group, which becomes a small batch for painting. When that’s finished, I’ll go through the batch checking out models to see if they need anything else done – belts, buckles, whatever. If they don’t, then I can actually call that model finished! So for me, entering this ending stage is very exciting, because the psychological obstacle of having sixty scowling warriors staring at you on a painting table makes the sense of achievement that much greater. And the increased sense of achievement will make me want to play more, meaning it’ll be more likely that I manage to organise a game!

corsairs

Another thing I was doing with my free time was planning a role-play campaign. I’ve got a rough skeleton story sketched out, I just need to flesh and structure it a bit more and see what it becomes. My gaming group also have a role-play campaign going that was geographically inaccessible to me, but has fortunately moved closer, that I’m now invited to. That’s a weekly affair that will score many many points on the ‘play more’ part of the deal, and possibly save me the trouble of buying new rulebooks – role-play groups are great for borrowing and sharing books, or buying second-hand. That should also help nip the temptation to spend in the bud.

I think role-playing games are one of the best kinds of games for a frugal and/or social gamer – you might well buy a few expensive rulebooks, but you can bet that someone else in the group has done the same and that becomes a pooled resource. To get started, all you need is to borrow some dice (or still rather frugally, buy your own set for a few pounds) and there you go! I’d heard somewhere that they first took off in popularity around the time of a recession, where people were watching their spending and to have a game based almost solely in imagination was a very frugal way of enjoying yourself – it may not be true, but it sounds plausible!

So to recap, I’ve had a lousy time of not playing enough games. Real life has been interfering, preventing the planning of games nights (for my board games fix) and regular wargaming opponents. But it looks like regular gaming is getting back on the agenda, and if there’s one thing that I’ve learned from my new year’s resolution experiment, it’s that having a real plan of action (not just a hopeful goal) will make all the difference. So you can expect next year’s plans to be much more solid!

Learning Unit Testing VI – Code Coverage

Before I get into finally finishing off that blasted page 10, I thought I’d go through a code coverage run to see how I was doing. Test Driven Development, see, everything should be covered by a test.

image

7.41% of the code is not covered by tests! I must be doing this wrong…

image_3

Phew, that was a relief. Turns out all of that uncovered code is in the WrongPhaseException I created from the Exception snippit without thinking about it. Activating the code coverage colouring in the code shows me what I’ve missed:

image_4

Because I only use one constructor out of a possible four, it counts as only 25% coverage and brings my average code coverage way down.

If I was to remove all those extra constructors (and leave them to the default Exception behaviour), would it improve my code coverage score?

image_5

Absolutely. It might be a bit like cheating (those methods are still not covered by tests), but since they’re core parts of the framework it doesn’t feel necessary to me. Short and sweet, on to part VII!

This is a learning project I am documenting in order to teach myself TDD and unit testing – as I publish this, I have already written many parts in advance but I want to know what I’m doing wrong! If you see improvements or corrections, either to the code or the process, please leave a comment and let me know! Introduction to this project can be found here.

Learning Unit Testing V – Refactoring Mistakes

I implied in the last post that I had made a mistake when I moved the MoveModel code into the Model class from the MovementManager class. Now, tests on the MovementManager class are actually testing functionality in the Model class. I also discovered that I am not properly testing the ‘GetDistanceFrom’ method with known data at all. This will have to be corrected.

Since I already have Model implementing an IModel interface, it’ll be easy enough to mock the Model part in the MovementManager. To see what tests are reaching into Model.MoveModel, I can just alter that method to throw an exception and see which tests fail.

image

Since this functionality has been moved to the Model class, these tests should actually be made against the Model class itself. Simple? Yes, but incorrect, as I found out next – it still fails on one condition and checking further, I don’t believe it’s checking the other one correctly. The validation of whether or not a model may make a move (ie, the distance is still under it’s Movement rate) is done in the MovementManager. My two options at this point are: move the validation back to the MovementManager and do a lot of mocking around the Model, or to move that validation into the Model as a ValidateMove method. Then the movement manager really becomes a mere progress tracker for the Movement phase… but I think that’s probably the best idea in this situation. Just one more test to move over (MoveModel_CannotMoveFurtherThanModelsMovement), then the GetDistanceFrom method needs to be tested. I think the following cases will need to be covered:

  • Full three-dimensional movement (all values change)
  • Two-dimensional movement (one value doesn’t change)
  • One-dimensional movement (only one value does change)
  • Cover reverse cases of each of the above (so the direction is backwards)

This test (worked on with a calculator and doodles to prove my working), however:

[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenAllValuesChange()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(2, 5, 7);
Assert.AreEqual(3.74, Math.Round(result, 2));
}

Shows me that either my test calculation is wrong or my original working is wrong. In the GetDistanceFrom method, this line

distance = Math.Sqrt(Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY)) + (differenceZ * differenceZ));

Should actually be

distance = Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY) + (differenceZ * differenceZ));

So I got the calculation wrong. Now the test passes, but another one breaks.

image_3

This is because that movement calculation now requires the model to move further than it’s allowed distance. Fixing that test’s values (from 3, 4, 5 to 2, 2, 2) and adding in the following tests:

[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenTwoValuesChange()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(1, 5, 7);
Assert.AreEqual(3.61, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenOneValueChanges()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 4;
double result = testModel.GetDistanceFrom(1, 3, 7);
Assert.AreEqual(3, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenAllValuesChange_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 2;
testModel.PositionY = 5;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3.74, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenTwoValuesChange_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 5;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3.61, Math.Round(result, 2));
}
[TestMethod]
public void GetDistanceFrom_CorrectAnswerWhenOneValueChanges_Reversed()
{
Model testModel = new Model();
testModel.PositionX = 1;
testModel.PositionY = 3;
testModel.PositionZ = 7;
double result = testModel.GetDistanceFrom(1, 3, 4);
Assert.AreEqual(3, Math.Round(result, 2));
}

Gives me 19 passes out of 19 tests. Excellent – I was expecting some of the 0-distance values being squared and rooted to throw some sort of calculation exception in .Net, but I can get along with this result.

This leaves me with my refactoring mess cleaned up, a calculation error solved, a method I somehow missed tests for covered properly, and all ready to tackle the last part of page 10 – a much longer page than I had initially expected. “Ooh look”, said the me at the beginning of the week, “half the page is picture and prose, and the other half is mostly descriptive. One or two posts to talk about design ideas and I’ll be on page 20 in a fortnight!” Isn’t hindsight awesome.

This is a learning project I am documenting in order to teach myself TDD and unit testing – as I publish this, I have already written many parts in advance but I want to know what I’m doing wrong! If you see improvements or corrections, either to the code or the process, please leave a comment and let me know! Introduction to this project can be found here.

Learning Unit Testing IV – Diagrams and Mathematics

Programming uses maths. It’s hard to ignore sometimes, especially when modelling something that is inherently graphical and position based such as a game.

I’ve decided to give the models three different position indicators – PositionX, PositionY and PositionZ. This will describe their exact position anywhere on the board – including on a ladder, a walkway or the ground. When they are given instructions to move, they should change those position variables accordingly – but not past the maximum move distance.

My two options are to either pass in a distance and direction (both X direction and Y direction, like an aircraft would need to navigate) or a new set of position points – in essence, saying precisely ‘go here’. In the first, the new position would need to be calculated, and in the second the distance would need to be calculated. Either way, I’d need to write both sets of code at some point.

I think that it will be easier to back-track the distance and directions from a set of positions than it would be the other way around. Transforming a simple co-ordinate of (X, Y, Z) – where X is East-West, Y is North-South and Z is Up-Down – such as (1, 2, 1) to a new position of (2, 1, 2) tells me that the model has moved up a slope to the North-East for a distance of… actually, that bit gets harder. But it’s at least easy to work out with trigonometry!

image

On a two-dimensional plane, it is fairly simple to work out – as on the (hastily scribbled, not-to-scale) diagram to the left. This brings back distant memories of Pythagoras – a2 + b2 = c2 – or, the square root of the difference in X + the difference in Y is the distance between the two points.

On a three-dimensional world, this is a bit more complicated – it has to be reduced to two different two-dimensional triangles to calculate the distance. The difference between two points is the ‘difference in X’ value of the second triangle. Another way of putting it would be √ (√ ((X1 – X2)2 + (Y1 – Y2)2) + (Z1 – Z2)2). Excellent.

In my original example then, the answer would be 1.554 arbitrary units. I could work out the directions (angles) by using more of my dusty trigonometric knowledge, but I only need to know the distance at this point. All I need to know are some test values that give a value above a model’s Movement rate and some under, so I can test the outcomes of the MoveModel method. In the case of overshooting a model’s permitted movement, I think I’ll throw a new exception. I can see (a few pages down the line) that the model is going to need to be able to tell it’s distance from other objects anyway, so this could be checked before attempting to move the model.

Time for a test! These values will move the model just a smidgen over 4 units.

[TestMethod]
public void MoveModel_CannotMoveFurtherThanModelsMovement()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
decimal newX = 5;
decimal newY = 6;
decimal newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

The code to pass this in the MovementManager is:

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ))
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
}

And in the Model itself is:

public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }
public double GetDistanceFrom(float positionX, float positionY, float positionZ)
{
double distance = 0;
double differenceX = this.PositionX - positionX;
double differenceY = this.PositionY - positionY;
double differenceZ = this.PositionZ - positionZ;
distance = Math.Sqrt(Math.Sqrt((differenceX * differenceX) + (differenceY * differenceY)) + (differenceZ * differenceZ));
return distance;
}

I can’t help but think that I am still over-designing this, but it feels about right to me. Finally, the test to ensure that the model actually does move:

[TestMethod]
public void MoveModel_PositionHasChanged()
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
Assert.AreEqual(5, testModel.PositionX);
Assert.AreEqual(4, testModel.PositionY);
Assert.AreEqual(3, testModel.PositionZ);
}

Which requires a change to MoveModel –

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ))
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
else
{
testModel.PositionX = newX;
testModel.PositionY = newY;
testModel.PositionZ = newZ;
}
}

Next, the situation that a model may move in two goes – and cannot go above it’s movement rate in both chunks. For this, we’ll have to record the distance moved.

[TestMethod]
public void MoveModel_TotalMovementInASingleTurnCannotExceedModelMovement_ThrowsArgumentException()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 5;
float newY = 4;
float newZ = 3;
movementManager.MoveModel(testModel, newX, newY, newZ);
movementManager.MoveModel(testModel, 0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
}

Movement of a model is starting to take on several different, inter-related actions so I’m going to move that stuff into the Model class itself. MoveModel in the MovementManager becomes simpler:

public void MoveModel(Model testModel, float newX, float newY, float newZ)
{
if (testModel.Movement < testModel.GetDistanceFrom(newX, newY, newZ) + testModel.TotalDistanceMoved)
{
throw new ArgumentException("The model cannot move further than it's Movement rate.");
}
else
{
testModel.MoveModel(newX, newY, newZ);
}
}

And the addition to the Model class is:

public double TotalDistanceMoved { get; private set; }
public void MoveModel(float positionX, float positionY, float positionZ)
{
this.TotalDistanceMoved += GetDistanceFrom(positionX, positionY, positionZ);
this.PositionX = positionX;
this.PositionY = positionY;
this.PositionZ = positionZ;
}

Next is to make sure we can make multiple moves without going over the limit and throwing an exception:

[TestMethod]
public void MoveModel_MakeTwoSmallMovementsWithoutGoingOverMovementRate()
{
bool correctExceptionThrown = false;
try
{
Mock<IGameManager> mockGameManager = new Mock<IGameManager>();
MovementManager movementManager = new MovementManager(mockGameManager.Object);
Model testModel = new Model();
testModel.Movement = 4;
testModel.PositionX = 0;
testModel.PositionY = 0;
testModel.PositionZ = 0;
float newX = 1;
float newY = 1;
float newZ = 0;
movementManager.MoveModel(testModel, newX, newY, newZ);
movementManager.MoveModel(testModel, 0, 0, 0);
}
catch (ArgumentException ex)
{
correctExceptionThrown = true;
}
Assert.IsFalse(correctExceptionThrown);
}

This doesn’t need any new code, it just proves that the existing code still works. Finally, there needs to be a check that the TotalDistanceMoved will reset to 0 at the beginning of each turn. What is going to be the trigger for that? Currently, the only place that a new turn is known about is the GameManager, and the IncrementPhase method. The question is, therefore, how should the model be informed of this change? Should the GameManager contain a collection of all the models currently in the game, so the IncrementPhase method can just iterate that collection? Or should models be held elsewhere, and subscribe to a ‘new turn’ event that is triggered? I think it makes most sense for the models to be stored in the GameManager – at least at this time – and for them to expose a ‘new turn’ method.

I have become aware as I am refactoring this code around that I’m starting to break the isolation of the unit tests – some tests are calling methods in classes that are not the class under test. This will obviously need to be refactored, but I’d like to finish the current train of thought first. To do that properly though, I need to add a new test class – ModelTests – and test the NewTurn method on that as well as making sure the GameManager calls NewTurn on each of it’s (mocked) Models. Testing these two things becomes an integration test, and cannot guarantee which class/method is actually responsible for failing a test.

[TestMethod]
public void IncrementTurnPhase_CallsNewTurnOnModels()
{
GameManager manager = new GameManager(2);
Mock<IModel> mockModel = new Mock<IModel>();
manager.Models.Add(mockModel.Object);
manager.IncrementPhase(); // Go to Shooting
manager.IncrementPhase(); // Go to Close Combat
manager.IncrementPhase(); // Go to Recovery
manager.IncrementPhase(); // Go back to Movement
mockModel.Verify(item => item.NewTurn(), Times.Once());
}

In the above test, I am adding a mock model into the GameManager, then verifying that the NewTurn method is called once. I add the Models property, create an IModel interface, change the IncrementPhase code to

public void IncrementPhase()
{
if (CurrentPhase == TurnPhase.Recovery)
{
CurrentPhase = TurnPhase.Movement;
if (CurrentPlayersTurn == NumberOfPlayers)
{
CurrentPlayersTurn = 1;
}
else
{
CurrentPlayersTurn++;
}
foreach (IModel model in this.Models)
{
model.NewTurn();
}
}
else
{
CurrentPhase++;
}
}

And… four tests fail on me!

image_3

This is exactly the purpose of unit testing. In this case, I realised that the Models collection (List<IModel>) hadn’t been initialised – these tests suddenly failing are a result of the turn ending and attempting to iterate through a collection that hasn’t been set up yet – a NullReferenceException. One quick tweak to the constructor, and they’re all passing again.

Finally, the test on the Model side to make sure that it sets TotalDistanceMoved back to zero.

[TestClass]
public class ModelTests
{
[TestMethod]
public void NewTurn_SetsDistanceMovedToZero()
{
Model testModel = new Model();
testModel.TotalDistanceMoved = 4;
testModel.NewTurn();
Assert.AreEqual(0, testModel.TotalDistanceMoved);
}
}

And the code in Model being insultingly simple:

public void NewTurn()
{
this.TotalDistanceMoved = 0;
}

Thirteen tests so far, and all passing. A quick lesson in how unit tests can quickly point to something going awry – though I am sure more important lessons will come along as I move through the project – and we’re almost to the end of page 10 in the rulebook. This has been a long section, and it’s a good point to leave it at.

This is a learning project I am documenting in order to teach myself TDD and unit testing – as I publish this, I have already written many parts in advance but I want to know what I’m doing wrong! If you see improvements or corrections, either to the code or the process, please leave a comment and let me know! Introduction to this project can be found here.

Does anyone like spam?

I’ve just had to put CAPTCHA on the blog comments here, because of too much spam. The spam filters are fine, but there was just too much spam being added.

Part of the problem was that BlogEngine.NET’s SQL provider deletes a post (!) before re-adding it, with every comment, all over again. So to add a new comment, every other comment on that post is deleted and re-added. To delete a comment, the same thing happens. With over 20,000 spam comments (and about 15 genuine ones), deleting comments was going to be a problem (and slow as hell!)

I was only really bothered by this when my hosting company informed me I was over quota – about 2.5GB over my 1GB limit. I traced this to the database, and after (manually) clearing out the spam comments, couldn’t fathom why it was still too high. The database itself was only about 6MB (as a backup file).

It turns out all that database activity was being logged, and the log file was over 3GB. So I can’t just allow rampant spamming, even though the filters were really pretty clever.

At some point, I intend to re-write the SQL provider for this blog that will help me keep that sort of thing to a minimum – I was gobsmacked when I realised that if I edit a post (for example, to correct a mis-spelled word, add a tag, etc) every comment was deleted and re-added. Even to add a comment, every comment is deleted and re-added. Surely, that’s not necessary… but I have other projects to get out of the way first. Maybe a resolution for next year?