Stuart Breckenridge

A 1,000 Year Simulation of Football Manager

“That’s right. You’re not seeing wrong. 1000 years of holidaying in FM15, in just England. I started this on March 4th and it took 58 days of simming to get to 1000 years. And now that it’s all over and the data is all compiled…”

Lorf_Yimzo


Over the years I’ve lost so many hours to Football Manager but I only last around a maximum seven seasons before starting all over again, so when I saw that someone had simmed 1,000 years worth of the game, I couldn’t help but take a look at some of the more outrageous statistics.

####Premier League

  • Most Times Winner: Sheffield United (168)
  • Highest Attendance: 112,278 (Burnley vs Preston)

The current big four definitely fall back from their role as glory custodians and let Sheffield United in. Burnley – at the Harry Potts Arena – racking up the highest attendances.1

####FA Cup

  • Most Times Winner: Burnley (101)
  • Highest Attendance: 126,047 (Bolton vs West Ham) (in 1923)

Burnley, not content with having the highest attendances across the land, also one of the FA Cup big shots with the most wins. It’s good to see that the highest attendance has stood the test of time.

####League Cup

  • Most Times Winner: Sheffield United (90)
  • Highest Attendance: 112,278 (Burnley vs Preston)

Sheffield United really get their game on in domestic competition, while Burnley’s Harry Potts Arena again hosts the highest attendance.

####Champions League

  • Highest Attendance: 523,945 (FC Red Bull Salzburg vs Red Star)
  • Highest Average Attendance: 576,199 (Celtic)
  • Top Goalscorer: Cristiano Ronaldo (17) (2013/14)
  • Most Goals in a Match: Lionel Messi (5) (2012)

I think there’s a bug as the average attendance is higher than the highest attendance. That being said, with over half a million people going to a match you can only imagine how good the view must be. Two more records that stand the test of time with Cristiano Ronaldo and Lionel Messi holding their own for more than a thousand years.

####Stadiums The Top 10 largest stadiums:

  1. Harry Potts Arena — Burnley (112,278)
  2. Wakefield Arena — Rotheram (105,915)
  3. Quaranta Arena — Sheffield United (90,273)
  4. Verhoeven Stadium — Bromley (87,436)
  5. Jaouen Arena — Plymouth (86,386)
  6. Bridges Stadium — Hull (85,693)
  7. Anderson Park — Southend (83,881)
  8. Wenger Arena — Arsenal (81,170)
  9. New White Hart Lane — Tottenham (70,312)
  10. The Stadium of Light — Sunderland (68,000)

It’s hard to piece this together. The only thing that’s immediately obvious is that The Stadium of Light must be falling apart, given that it’s over 1,000 years old.

####World Cup

  • Number of Times Scotland Win: 1

Excellent!

N.B.: I’m waiting to download the save game. Seemingly, Celtic won the SPL every single year of the entire simulation.

  1. Note: The Harry Potts Arena has a larger capacity that the population of Burnley.

    </li> </ol></div>


iCloud Voicemail

“Employees at Apple are reportedly putting a new service through its paces, one that would allow Siri to not only answer a missed call instead of a pre-set voicemail message, but give her the ability to record and transcribe those message for users to read as text later (via Business Insider).”

Mitchel Broussard


I think the idea of iCloud Voicemail is excellent. The adoption of Visual Voicemail – itself an outstanding feature – has been poor1 and that’s the fault of the carriers. They have, once again, presented Apple with a problem to solve and in the process cut off one their revenue streams.

  1. Only 10 carriers in Asia Pacific and Australasia support Visual Voicemail.

    </li> </ol></div>


App Transport Security, Cloudfront, and S3

App Transport Security is a new feature in iOS 9 and OS X 10.11 and it’s enabled by default. This means that you can’t use standard HTTP for requests without making changes to application’s Info.plist.

Take the following simple request:

let request = NSMutableURLRequest(URL: NSURL(string: "http://something.cloudfront.net/some.file")!)
request.HTTPMethod = "HEAD"
let queue = NSOperationQueue()
let session = NSURLSession(configuration: sessionConfiguration, delegate: nil, delegateQueue: queue)
let downloadTask = session.downloadTaskWithRequest(request) { (url, response, error) -> Void in
            print(response)
        }

This request fails in iOS 9 with the following error and a nil response:

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. 

Temporary exceptions can be configured via your app's Info.plist file.

As Cloudfront supports HTTPS the request URL can be changed:

let request = NSMutableURLRequest(URL: NSURL(string: "https://something.cloudfront.net/some.file")!)

However, when running the request a different error appears:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

For my specific configuration – Cloudfront CDN with data hosted in Amazon S3 – Forward Secrecy is not enabled (or, at the very least, it’s causing issues). You don’t have to tear down ATS entirely to get things working, you just need to disable the requirement for Forward Secrecy in your Info.plist:

<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>something.cloudfront.net</key>
			<dict>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
			</dict>
		</dict>
	</dict>

This resolved my issue, hopefully it helps someone else to.


2XU Compression Run 2015

The postponed 2XU Compression Run is happening on August 2nd. While the route has yet to be announced, a few extra bits of information have trickled out:

“Flag-Off Time: 4.30am (21.1KM), 7.30am (10KM) and 8.30am (5KM)
Venue: Marina East Drive (Open field beside 201 Marina East Drive, Singapore 029997)


Due to the changes in the date and venue of the run, please also note that there will be changes in terms of the layout and race route. While the route may not be as ideal as we would like it to be, the replacement route has been derived with the best of our abilities, given the sudden change in circumstances and because many venues were booked a year in advance. The updated race route will be announced this week due to restrictions by stakeholders.

2XU


The start point is hard to get to, so have a look at the getting there guide.


Code Review

When I first got interested in programming – around 2009 – the first app I made was a little utility to help you pick your lottery numbers. It was called Lucky Dip and it sold exclusively in the UK App Store and it very quickly went from being £0.69 to being free.1

In the spirit of continual improvement I’m reviewing my younger self’s code, and boy is it a painful experience.

The problem statement: generate a set of six unique numbers between 1 and 49.


Younger Self

I’m sure I attacked the problem in the following way:

  • find out how to generate numbers within a specific range;
  • generate six of them; then,
  • compare them all against each other individually to make sure they are unique.

This is what my code looked like:

- (NSArray *)generateLottoNumbers
{
        // Generate Numbers
    int n1 = arc4random() % 49 + 1;
    int n2 = arc4random() % 49 + 1;
    int n3 = arc4random() % 49 + 1;
    int n4 = arc4random() % 49 + 1;
    int n5 = arc4random() % 49 + 1;
    int n6 = arc4random() % 49 + 1;
    
        // Check uniqueness
    if (n1 == n2 || n1 == n3 || n1 == n4 || n1 == n5 || n1 == n6 ||
        n2 == n3 || n2 == n4 || n2 == n5 || n2 == n6 ||
        n3 == n4 || n3 == n5 || n3 == n6 ||
        n4 == n5 || n4 == n6 ||
        n5 == n6)
        {
            return [self generateLottoNumbers]; // Duplicates detected.
        }
    
    	// Return a sorted array.
    else
        {
        NSMutableArray *numbers = [NSMutableArray arrayWithObjects:@(n1), @(n2), @(n3), @(n4), @(n5), @(n6),  nil];
        NSArray *array = [numbers sortedArrayUsingSelector:@selector(compare:)]; 
        return array;
        }
}

The code was then called with:

	NSArray *numbers = [self generateLottoNumbers];

This existed in each view controller in a different incarnation, suitable to each lottery game (typed out every time).2 Talk about not having reusable code and massive view controllers.

Current Self

What I’d do now is create reusable code so each view controller for each lottery game called the same function. I’d start with a protocol:

protocol LottoNumbers
{
    func generateLottoNumbers(count:Int,maxRange:UInt32) -> [Int]
}

I’d then extend UIViewController to conform to the LottoNumbers protocol3. The function makes use of a Set to ensure that there are the correct amount of unique numbers:

extension UIViewController:LottoNumbers
{
    func generateLottoNumbers(count:Int,maxRange:UInt32) -> [Int]
    {
        var i = 0
        let uniqueSet = NSMutableSet(capacity: count)
        var numberArray = [Int]()
        
        repeat {
            let genNumber = (Int(arc4random() % maxRange + 1))
            uniqueSet.addObject(genNumber)
            numberArray.append(genNumber)
            ++i
        } while i < count
        
        if uniqueSet.count != count
        {
            return self.generateLottoNumbers(count, maxRange: maxRange)
        }
        
        numberArray.sortInPlace({$0<$1})
        
        return numberArray
    }
}

This code can be reused depending on the rules of the game and it also prevents having a massive view controller:

let numbers = generateLottoNumbers(6, maxRange: 49) // Lotto.
let numbers = generateLottoNumbers(5, maxRange: 50) // Euromillions.
// etc...

There are always better ways of doing things. However, the original version worked and that’s all that mattered at the time.

  1. I had lofty ambitions of World domination that didn’t last. ↩︎

  2. There were three others: Hotpicks, Thunderball, and Euromillions. ↩︎

  3. This could also be achieved with an Objective-C tags. ↩︎