Thursday, August 16, 2007

Tiny little bug

It's always the little ones.

Today I was developing the league ranking system, essentially a way for the game to record the finishing positions of all the teams in a league, and also for the teams to be ordered correctly. This can then be used by competitions to determine seedings, or collecting only the top 8 teams to play.

While testing this out I was frustrated for several hours by a bizarre error. At the end of the season, all the teams' rank information are updated accordingly. This is then followed by promotions and relegations, which involves updating the current level each team are playing at. Irritatingly, doing so tended to set the "rank level" - the level the team were playing at last season - to 0, the highest level available. As far as the game was then concerned, if Cardiff City won the Championship, they're ranked as high as Manchester United.

After a while I had traced it down to the exact function that sets the current level. A function that simply should not fail. I feared the worst - if a part of my database storage and retrieval code was broken, the entire database could be compromised. Sure, I have backups but I'd still need to find out the error, and if it's damaging I'd need to code an entire routine to reorganise the data and ensure it's fine.

Eventually, and naturally, I traced it to simply using the wrong variable at a crucial moment. My database works by only using the required storage for any given maximum data value in a field - if the field holds the numbers 0 to 15, it will use four bits. The next four bits in the byte will be used by something else. This enables me to store a great deal of data in a much smaller space. In order to store two values in a single byte, I need to be able to "mask out" the irrelevant data at any given point. This was the broken bit, with the code therefore ignoring the masking and wiping the entire bite before storing my data.

I think, but currently have no proof, that this error was the cause of a few other issues dotted here and there with some competitions "forgetting" what league they were part of if I edited them after setting the league up. All it would take is one editing of a preceding value and that data goes out the window.

Sunday, August 12, 2007

Ups and Downs

Individual competitions are almost complete. The engine is fully capable of coping with differing numbers of entrants, so there are only a few things left. Chief among these is the existence of what I've been terming the "half group" structures. The most prominent of these is the MLS - two groups, but with matches not restricted to those in your own group. Yesterday I discovered that it's not just the Americans using this system, and that any Englishmen still bitter at those "damn Yanks" for calling the sport soccer need to have a few words with some of the powers in their own garden. At the non-league level, at least

The Northern Premier League's first division was restructured this season in accordance with the FA's plans on sorting out a clear league pyramid. Unlike the other leagues at this level, the two created leagues (North and South) only have 18 teams, instead of 22. This caused a bit of a fuss among the clubs because 34 game seasons aren't really helpful, and the NPL duly responded not by increasing the league size or another cup competition to make up the deficit, but by splitting each league in two - sort of.

Each league is split into two groups of nine, on a regional basis. Each team will play those sides in their own group three times, and those in the other group once, thus giving an extra eight games each. Unlike the MLS, performance relative to the other teams in your group counts for nothing - it's the overall league table that matters. Whilst to the casual observer they don't seem to share structural DNA, the generation of fixtures and general workings are practically the same from my point of view.

The English league itself has been created in the game now, down to Step Four of the National League System, or the eighth level overall if you prefer. Whilst doing this, I helped myself out by introducing a few handy functions and changing the way clubs get added to the database. I can now duplicate an entire competition, which is handy given that most share similar characteristics with few changes. The club spreadsheets I'm using, one per division, contain club info as well as their city and stadium. I've ditched seating information, largely because the information simply isn't conveniently available and to use it would slow the input process down. I reckon now I can add an entire division in about a half hour, including creating the structure in the game and adding it to the league structure.

I make that about... oooh... 390 hours of work to get the world in there.

The regionalisation of lower levels is working brilliantly, although a few hiccups earlier did give me a bit of concern. The first was the bizarre omission of Newcastle Blue Star from the NPL First Division North in the second season. As the northenmost club at that level (by some distance), they definitely should have been there. They weren't in the First Division South either. Well, not the right one, they were in the Isthmian League First Division South. It turns out that I'd added the team with the city "Newcastle-upon-Tyne", and omitted the coordinates because I knew the city to be in the database. It was, sans hyphens, and the game thought that Newcastle Blue Star play in the heart of the world, in the Atlantic Ocean off the coast of Africa. I can't be arsed coding in severely flooded pitches, so I just set them to the right place.

I later got concerned that the game wasn't properly dividing teams up into Isthmian and Southern leagues, but I quickly discovered that I'd placed Bury St Edmunds in the West, not the East. Oh well. Everything else was positioned rather lovely, so I did a little dance.

Promotion and relegation isn't yet done. I've worked out the process and in theory it's fine. Promotion is dealt with first, with teams promoted provided they meet the criteria, and provision is there for other teams to take their place if necessary. Relegation is then dealt with, and repreives are available if the number of teams coming up isn't enough.

I then read about the Italian Coppa Dilettanti, a competition played in Italy between sides in the Eccellenza and Promozione, the sixth and seventh levels of the Italian league system. The quirk of this competition is that the winners are promoted to Serie D. I like quirks, so I instantly wanted to make the Eccellenza available, and thus this cup competition playable.

Unfortunately, my league system doesn't cope with teams potentially being promoted more than one level. In fact, it freaks out completely and doesn't know what's going on, leading usually to the level in between the two having far too many teams. I could spend time devising a new system, but I've decided that for now it just isn't worth devoting time to a non-essential. Not when there's so much else to do.

At the moment I'm looking at ways to make inputting the promotion data as stress free as possible. Currently I have to set up the data in the competition itself, and then let the league know where to expect the promotions/relegations to come from and what priorities to assign to them. I should be able to get some of that done quicker. Once that's done, I'll get the English system finished up and tested, and use that as a basis for working on the focus system and other details.