Monday, November 17, 2014

Qute UI revamp and Deck Stats

A little over a week ago I posted about the first draft of my Qute MTG Stats tool. This past weekend I had some time between matches of magic to implement some new ideas I had for the project. These include:

  • Adding notes to events such as deck played and decks played against
  • See stats by deck for decks you've added to the event list
  • Export event/opponent lists to CSV files
  • Export full stats to clipboard/text file
  • Save edited data to a .qute file
  • Load data from a selected .qute file
  • Added prompts to let the user know when actions complete successfully
  • Added in application help prompt

I've also moved away from the original tabbed setup I started with to separate to allow the user to view information side by side:

For a full set of screenshots check here.

For those interested in giving this a try yourself, you can always download the latest Windows binary form here. For those using a superior operating system, simply install pyside, download the latest snapshot, and run the

If you have any suggestions or feature ideas let me know with a comment below.

~Jeff Hoogland

Friday, November 7, 2014

Qute MTG Stats Tool

Late last year I wrote an Excel workbook that you could use to analyze your Magic the Gathering match history using VBA. While it was functional, being contained in an Excel workbook meant my tool was tied to closed source software and was limited by the bounds of Excel.

Today I would like to share the first draft of a new project of mine - Qute, a stand alone MTG Stats Tool:

For those interested in giving my tool a try, you can find install and usage instructions here.

The main thing I am looking for is suggestions on how to improve this tool. What information would be useful to provide that can be scrapped from the data provided in our DCI history? If you have any ideas or find any bugs drop a comment below or open up a ticket on GitHub!

~Jeff Hoogland

Wednesday, November 5, 2014

PyPair: A Python Library for Pairing Swiss Tournaments

Something I've spent a few hours on in the last month is a small python library, that I am calling PyPair, that allows you to easily manage a Swiss-System Tournament. For those unfamiliar with this concept:

"A Swiss-system tournament is a non-elimination tournament format. There are several rounds of competition, but considerably fewer rounds than in a round-robin tournament, so each competitor (team or individual) does not play every other competitor. Competitors meet one-to-one in each round and are paired using a predetermined set of rules designed to ensure that as far as possible a competitor plays competitors with the same current score, subject to not playing the same opponent more than once. The winner is the competitor with the highest aggregate points earned in all rounds."

A short example of using PyPair:
from pypair import Tournament

Players = { 1:"Tim",

to = Tournament()

for player in Players:
    to.addPlayer( player, Players[player] )

pairings1 = to.pairRound()

print pairings1
Yields the output:

{1: [1, 7], 2: [2, 6], 3: [3, 5]}

Which is a simple python dictionary where each key is a table number that corresponds to a list of the players playing at that table.

If you would like to see a more complex example see here.

If you are interested in the math behind the pairings, PyPair essentially does the following when you call the pairRound() function:

Group players by point totals
Starting with the group who has the most points:

  • Create a graph with all players in current point total
  • Connect players in the graph that have not played yet
  • Use a Blossom based algorithm to compute a maximal matching of the graph
  • Take any unpaired players and add them to the group with the next highest point total
Repeat until there are one/none unpaired players
If there is one unpaired player, assign a bye
Return a python dictionary of the pairings

The networks created by PyPair are implemented using the NetworkX library.

If you have any suggestions for improvement or find an issue feel free to open a ticket on GitHub or leave a comment below.

~Jeff Hoogland