### sfmagic.org Rewrite: Pod Division

Individual draft groups in MTG are called “pods”. The sfmagic group runs drafts every Wednesday (19:30, Milano’s Pizzeria), and it’s these drafts that I’m rewriting a site to track the results of. At the moment I’m writing the data entry side, and took a slight detour to write a utility to help in the weekly organization.

We use the results from the site (sadly out of date at the moment, which is one of the reasons why I need to get efficient data entry done) to seed players (details here), so each Wednesday I (or someone else) ends up checking the names of those people who show up off a list of the seeding rankings.

We alternate between putting similarly-seeded players together and putting differently-seeded players together. Either way, dividing the attendees up into pods can be time-consuming to do on paper. The ideal pod size is eight, the minimum is six, and the maximum is ten, although we will if we absolutely have to draft with eleven (that is, if only eleven players show up). The time-consuming part occurs when three players show up after the pods have been written down, and everything has to be redone. This is obviously a task that would be better suited to a computer.

So I wrote a JavaScript/HTML pod division page. The most interesting part of it is probably the function that does the pod size calculations, i.e. decides on how many pods there are and how many people go into each one. I’m sure there’s a more efficient way to write it (there always is), but this is my pared-down version (which does depend on jQuery for extend and grep, to save some lines):

function podSizes(numplayers, options) { /* Return number of pods such that no pod is smaller than min and no pod is greater than max, while also maximizing the number of ideal pods. */ //Set defaults and override with options, if any. var defaults = { min: 6, max: 10, ideal: 8 }; var o = jQuery.extend(defaults, options); //If less than indivisible, there's no point in continuing. if (numplayers <= (o.min*2)) return [numplayers]; //Set up the pods var pods = []; function process(numplayers) { //This is a recursive function that will process until numplayers is 0 var remainder = numplayers % o.ideal; if (numplayers==0) return; if (numplayers <= (o.min*2)) { //Just in case we end up with that condition here. pods.push(numplayers); return; } if (remainder==0) { //Divisible by ideal, pretty easy pods.push(o.ideal); process(numplayers-o.ideal); } else if (remainder >=o.min) { //A bunch of ideal pods, plus one other acceptable pod. pods.push(remainder); process(numplayers-remainder); } else if ( ((numplayers-o.ideal) > (o.min*2)) || ((numplayers-o.ideal) >= o.min && (numplayers-o.ideal) <= o.max) ) { //Extracting an ideal pod leaves us with a good number. pods.push(o.ideal); process(numplayers-o.ideal); } else if (((numplayers-o.min) >= o.min && (numplayers-o.min) <= o.max) || ((numplayers-o.min) > (o.min*2)) ) { //Extracting a min-size pod will leave an acceptable number pods.push(o.min); process(numplayers-o.min); } else if (numplayers >=o.min && numplayers <= o.max) { //Last pod, acceptable size. This could perhaps be an else with no conditions. pods.push(numplayers); return; } else { //insert error condition here--should never get here. } }; process(numplayers); var idealPods = jQuery.grep(pods, function(n, i) {return (n==o.ideal);}); var otherPods = jQuery.grep(pods, function(n, i) {return (n!=o.ideal);}); otherPods.sort(function(a,b) {return b-a;}) pods = idealPods.concat(otherPods); return pods; };

This works for all the numbers I've tried—which is all we're going to encounter, as it gets easier, not harder, as the number goes up. I haven't tried playing around with the min/max/ideal numbers that much, but it appears to work relatively well. The obvious enhancement (unnecessary for us) would be to include numbers which are simply unacceptable—for example, it's possible that some scenarios/games would have a minimum of four, a maximum of twelve, an ideal of eight, but six would be an unacceptable number, in which case that would need to be factored into the function. Since we don't have that constraint, though, I don't think I'll write it in.

The full version includes a list of all the players and their seeding, takes the names of the attendees and the type of seeding as input, and outputs the pods each with the correct players and their randomized draft positions. It probably took me several hours to write. It will take some time for that investment in time to be realized, but on the other hand it was fun to write, and will make running the drafts feel a lot less like hassle (which, who knows, might even help my drafting results).