Monday, September 9, 2013

Advanced CFL Stats - Week 11

The week is over, so it's time for more stats.

This week the Riders got a little less lucky, the Bombers got a win in the new stadium, and the Eskimos just can't buy a break.


I stream-lined the chart a bit this week and it's presented in a slightly different format, as my stats are now in a database instead of a spreadsheet, so I can store more and do cooler things, like:

Big Win Percentage.

Big Win Percentage is a simple stat, created by Jim Glass. It's based on the premise that football by nature is a game that can be heavily influenced by luck. A bad call, a fumble recovery, a gust of win; these are all things which can turn a close game into a win or a loss. According to Brian Burke (the guru of NFL stats), the outcome of more than 40% of NFL games is determined by random chance. This makes judging a team by it's record a difficult proposition (especially in the NFL, where teams don't play every team in the league).

What Mr. Glass's formula does it try to account for that luck by giving teams credit for "Big Wins", defined as a game decided by 9 or more points. 9 points makes a good cut off because it is the border between 1 and 2 possession games.

The formula is simple - games won by 9+ points count as a "Big Win", games lost by 9+ points are considered a "Big Loss", and all the rest are considered ties. If you read the article linked above, you'll see that he's found that teams with a high number of "Big Wins" in a season tend to fare much better in the playoffs. We'll see if that holds true for the CFL (I'm compiling data back to 1990 for a post later this week), but in the mean time, I'm going to include it on the chart for this week.
 

Py W = Pythagorean Wins, Projected = Py Wins over 18 games

The Riders remain the best team in the league based on Py Expectation, but they are no longer considered the luckiest team in the league, that honour now goes to Calgary.  Edmonton remains the unluckiest team so far, nearly 3 wins below expectation.  Winnipeg, despite a win over the Riders this week, still sits at the bottom, though they are still considered unlucky by the formula.

Coming soon...

As noted above, I've been collecting data, back to 1990 so far.  I plan to do a post to highlight some of the interesting points once I have a bit more information gathered.

- Mike

Friday, September 6, 2013

CFL Pythagorean Wins


I'm a big believer in statistics and analysis when it comes to sports.  As noted by some on /r/cfl previously, there is a significant lack of advanced stats for the CFL.  I'm not a statistician, nor do I have charting stats for each any every game like the NFL stats sites, so there are definite limits on what I can provide, but one stat I can calculate easily is Pythagorean Wins.

Bill James created the formula for baseball years ago, and it's been modified to better suit the NFL since then.  Obviously the CFL is not the CFL, but the season is of similar length and scoring numbers are also in the same ball park, so I believe the stat should apply fairly well to our league.  Down the line I will look at some past seasons and see if I can determine how well (or poorly) it actually does work.

The formula itself is based on the idea that not all wins are created equal, and that point differential is actually a better indicator of future winning percentage than actual wins and losses.  When applied to NFL games, the stat is a good indicator of future performance, both for future seasons, and second halves of the same season.

For a more detailed explanation from someone much smarter than I, check out Bill Barnwell's explanation on grantland.com.

With all of that said, we are at the half way point of the CFL season, so this is a perfect time to run the numbers on the first half and see what they might tell us.

Legend
P-W%: Pythagorean Winning Percentage, P-W: Pythagorean Wins, P W-L: Pythagorean Win-Loss,
Diff: Difference between Py Wins and Actual wins, P-W-T: Pythagorean Win Total (projected over 18 games)
 

By the numbers, Saskatchewan and BC are the luckiest teams of the first half, while Edmonton and Winnipeg are the unluckiest.  Despite being the luckiest team, the formula still believes that the Riders are the best team in the league, while Edmonton has been particularly unlucky, performing almost 2.5 wins below expectation. 

Teams which over or under perform the formula by a wide margin tend to fall back or climb closer to their expected win total as the season progresses, so according to Pythagoras, both Edmonton and Winnipeg fans should have some hope that their team will rebound slightly in the second half.  That said, there aren't many surprises here, other than some shuffling in the middle.  The formula believes that Toronto is slightly better than BC (but clearly isn't aware that Ricky Ray is injured), and that Montreal is slightly worse than Hamilton.

Friday, March 7, 2008

Serializable Dictionary

Some quick code for a VB.Net dictionary object which can be serialized to XML. Most of the credit goes to Paul Welter, who covers a C# implementation here.

This code is a port to VB with some minor structure changes. In Paul's example, each key/value pair is contained within <item> tags; in this version, the key is typed as a string and used as the tag. For our uses, this was simpler and resulted in slightly more readable XML output.

Imports System.Xml.Serialization

Public Class XmlDictionary(Of T)
Inherits Dictionary(Of String, T)
Implements IXmlSerializable


Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements IXmlSerializable.GetSchema
Return Nothing
End Function

Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
Dim valSerializer As New XmlSerializer(GetType(T))

Dim wasEmpty As Boolean = reader.IsEmptyElement
reader.Read()

If (wasEmpty) Then Return

While reader.NodeType <> Xml.XmlNodeType.EndElement

Dim key As String = reader.Name
reader.ReadStartElement()
Dim value As T = valSerializer.Deserialize(reader.ReadSubtree())
reader.ReadEndElement()

Me.Add(key, value)

reader.ReadEndElement()
reader.MoveToContent()

End While

reader.ReadEndElement()

End Sub

Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements IXmlSerializable.WriteXml

Dim valSerializer As New XmlSerializer(GetType(T))

For Each key As String In Me.Keys
writer.WriteStartElement(key)

Dim value As T = Me(key)
valSerializer.Serialize(writer, value)

writer.WriteEndElement()
Next

End Sub

End Class


The resulting XML will look as follows:

<?xml version="1.0"?>
<XmlDictionaryOfString>
<key1>
<string>val1</string>
</key1>
<key2>
<string>val2</string>
</key2>
<key3>
<string>val3</string>
</key3>
</XmlDictionaryOfString>


Note that the values are serialized and need not be strings. You may wish to check out Paul's code if you need non-string keys.

Friday, February 1, 2008

What the heck?

Anyone know what a _VbtlGapX_Y method is?

Some strange behavior here...we have a COM interface (from the same type library as the other) which we're implementing. All properties and methods of the interface are completely implemented, but on compile I'm getting four errors:

[Class Signature] does not implement interface member [Interface]._VtblGap8_2()
[Class Signature] does not implement interface member [Interface]._VtblGap11_2()
[Class Signature] does not implement interface member [Interface]._VtblGap26_2()
[Class Signature] does not implement interface member [Interface]._VtblGap171_2()


Its a rather ugly thing to try and search; exact searches for _VbtlGap8_2 give nothing at all.

Based on some googling and a little bit of guesswork, it seems that VTables are part of the COM-Interop system, and should normally be hidden in .Net. Its anyone's guess why that's not the case here.

Fortunately, I did find a solution...Bite the bullet and implement them:

public void _VtblGap8_2()
{
throw new Exception("Don't access this method");
}


Why a public method and not an explicit implementation? Because it doesn't work...it was the first thing I tried. Unfortunately, while that DOES compile, any attempt to instantiate the class will fail, throwing a Type exception. Public implementation was the only way I found to successfully compile and use the object, even if it means they are visible (and ugly) public methods on the class.

Anyone know of a better solution?

Wednesday, January 30, 2008

Fun with COM Part 1 - Interfaces

Early in our development process we encountered a problem with our COM objects; namely, they are not serializable and therefore cannot be (safely) cached. Fortunately, all of the objects used within VB6 implement a VB6 interface...as a result, the decision was made to create .Net classes can implement these VB6 interfaces, so they can (among other things) be made cacheable. It was not an easy task, however, thanks to some oversights in the VB6 code and a generally stupid decision on the part of Microsoft: Visual Basic 6 defaults all parameters to being passed by reference if not explicitly specified. As a result, we have many, many places in our VB6 interface which look like this:
Private Property Get IField_ControlIdx() As Integer
IField_ControlIdx = m_intControlIdx
End Property

Private Property Let IField_ControlIdx(p_intControlIdx As Integer)
m_intControlIdx = p_intControlIdx
End Property


When implemented in VB.Net, that (should) look like this:
Public Property ControlIdx() As Short Implements ...
Get
returns m_intControlIdx
End Get
Set(ByRef value As Short)
m_controlIdx = value
End Set
End Property


Unfortunately, that doesn't compile, instead giving the following error: 'Set' parameter cannot be declared 'ByRef'. Changing 'ByRef' to 'ByVal' makes the property valid, but not the class, which gives the following compile error: [PropertyName] cannot implement [Propertyname] because there is no matching property on interface [Interface]. Stuck.


Microsoft has the following article on this issue: http://support.microsoft.com/kb/316581

Their solution? "To resolve this bug, rebuild the COM library so that it passes arguments to property procedures by value instead of by reference." Well sure, of course THAT would work, but that comes with its own issues...in our case, the fact that it would mean roughly 50 VB6 classes that would require updating and testing. Our interface is shared with our windows application, which is well past the point of a core change, so this wasn't an option.



Fortunately, there is another solution: C#.

Because the parameters are passed by reference, the C# interpreter sees the set properties as methods:
public void set_ControlIdx(ref short value)


Alternatively, you can implement the interface explicitly:
void [InterfaceName].set_ControlIdx(ref short value)


This is how we handled it. By implementing the interface explicitly, we were able to create our own, valid public properties, while hiding the ugly ByRef versions. To keep things consistent, we had the explicit methods reference the cleaner, public methods, keeping the logic in the same place.
public short ControlIdx
{
get { return m_controlIdx; }
set { m_controlIdx = value; }
}

short [Interface].get_controlIdx()
{
return this.ControlIdx;
}

void [Interface].set_controlIdx(ref short value)
{
this.ControlIdx = value;
}



Hope that helps!




Additional note for VB developers:

We actually took an additional step in our C# classes. In order to keep the bulk of our logic in Visual Basic (I personally prefer C#, but this is a VB shop), we actually made our C# classes abstract, and our public properties are abstract as well.

Then, we created matching VB.Net classes which inherit from our C# classes and put the logic there. The result is an extra file, and an external class library, but we were able to implement our VB6 interface without changing it, and while still keeping the actual logic in VB.Net.

What's this for, anyway?

The purpose of this page is simple: to provide a singular place to find solutions to problems I've encountered in programming projects. Hopefully, I can save someone else some trouble :)



For anyone who may be interested in the background details, I'm currently working on a large projected which involves providing access to existing business logic via a .Net web service. Initially the service will utilized by an outside company developing their own web site front end, but we are also developing our own presentation layer for testing (and eventually our own public release).

The project utilizes the following technologies:

  • Visual Basic 6 - all existing business logic is via VB6, logic that is much too large to port to .Net at this time.

  • Visual Basic.Net - the web service and test presentation layer

  • C# - to resolve a compatibility issue, which I plan to touch on in my first actual post.

  • XML

  • Ajax