Topic: Inventory Draft

Inventory Draft is a JavaScript program you can copy and run in your browser.

EDIT: Visual guide: http://imgur.com/a/dbNaz#0
EDIT: You can now generate pauper drafts!
EDIT: You can now generate rares-only drafts!
EDIT: You can now specify how many of each rarity you want per pack!

How to "install"

  • Copy all of the code below

  • Open your favorite text editor (e.g. Notepad, Wordpad, GEdit, etc.)

  • Paste the code you copied into the editor

  • Save the file as "InventoryDraft.html" wherever you want on your computer

  • Open the file in your browser (e.g. right-click -> Open with Chrome)

  • In Deckbox, click inventory, hover over View and Hit Export

http://i.imgur.com/jaUBCQt.png

  • Make sure you select Rarity and Image URL options

http://i.imgur.com/AiGo1WO.png

How to run

  • Choose the number of players you want to generate packs for. There are 15 cards per pack and 3 packs per player.

  • Upload your CSV file you saved from Deckbox.

  • As soon as the file is chosen, the packs are created and displayed.

  • If you do not like what was picked, refresh the page and repeat the steps.

How to save

  • Once you have found a configuration you like, you may wish to save the file because it was randomly generated and cannot be reproduced

  • Right-click the page in your browser and select "Save As"

  • Name the file whatever you wish but make sure the file extension is ".html"

Here's the code:

<!DOCTYPE HTML>
<html>
    <head>
        <title>Inventory Draft</title>
        <script src="InventoryDraft.js" ></script>
    </head>
    <body>
        <p><a href="http://deckbox.org/forum/viewtopic.php?id=9790">More detailed instructions here</a></p>
        <p><b>Number of players (3 packs per player):</b> <input type="number" id="numPlayers" min="1" max="8" value="1" /></p>
        <p><b>Commons:</b><input type="number" id="numcommons" min="0" max="15" value="11" />
        <b>Uncommons:</b><input type="number" id="numuncommons" min="0" max="15" value="3" />
        <b>Rares:</b><input type="number" id="numrares" min="0" max="15" value="1" /></p>
        <p><b>Upload your Inventory CSV file here:</b> <input type="file" id="files" name="files[]" /></p>
        <output id="out"></output>

        <script>

    function CSVToArray(strData) {
        strDelimiter = ",";
        var objPattern = new RegExp(
            (
                "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
                "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
                "([^\"\\" + strDelimiter + "\\r\\n]*))"
            ),
            "gi"
            );
        var arrData = [[]];
        var arrMatches = null;
        while (arrMatches = objPattern.exec( strData )){
            var strMatchedDelimiter = arrMatches[ 1 ];
            if (
                strMatchedDelimiter.length &&
                (strMatchedDelimiter != strDelimiter)
                ){
                arrData.push( [] );
            }
            if (arrMatches[ 2 ]){
                var strMatchedValue = arrMatches[ 2 ].replace(
                    new RegExp( "\"\"", "g" ),
                    "\""
                    );
            } else {
                var strMatchedValue = arrMatches[ 3 ];
            }
            arrData[ arrData.length - 1 ].push( strMatchedValue );
        }
        return( arrData );
    }

  function handleFileSelect(opt_startByte, opt_stopByte) {

    var commons = [];
    var uncommons = [];
    var rares = [];
    var mythics = [];
    var commonsi = [];
    var uncommonsi = [];
    var raresi = [];
    var mythicsi = [];

    var numUn = document.getElementById('numuncommons').value;
    var numC = document.getElementById('numcommons').value;
    var numR = document.getElementById('numrares').value;
    var nameCol = "Name";
    var rarityCol = "Rarity";
    var imageURLCol = "Image URL";
    var common = "Common";
    var uncommon = "Uncommon";
    var rare = "Rare";
    var mythic = "MythicRare";
    var nameIndex, rarityIndex, imageURLIndex;
    var numPlayers = document.getElementById('numPlayers').value;

    var files = document.getElementById('files').files;
    if (!files.length) {
      alert('Please select a file!');
      return;
    }

    var file = files[0];

    var start = 0;
    var stop = file.size - 1;

    var reader = new FileReader();

    reader.onload = function(evt) {
        var contents = evt.target.result;
        var lines = CSVToArray(contents);
        var header = lines[0];
                
        nameIndex = header.indexOf(nameCol);
        rarityIndex = header.indexOf(rarityCol);
        imageURLIndex = header.indexOf(imageURLCol);

        for (var i = 1; i < lines.length; i++) {
            var line = lines[i];
            
            if (line[rarityIndex] == common) {
                commons.push(line[nameIndex]);
                commonsi.push(line[imageURLIndex]);
            } else if (line[rarityIndex] == uncommon) {
                uncommons.push(line[nameIndex]);
                uncommonsi.push(line[imageURLIndex]);
            } else if (line[rarityIndex] == rare) {
                rares.push(line[nameIndex]);
                raresi.push(line[imageURLIndex]);
            } else if (line[rarityIndex] == mythic) {
                mythics.push(line[nameIndex]);
                mythicsi.push(line[imageURLIndex]);
            } else {
            }
        }

        var output = [];
        var chosenc = [];
        var chosenu = [];
        var chosenr = [];
        var chosenm = [];
        var rand = 0;
        var count = 0;

        output.push('<p><i>', commons.length, ' - Number of commons<br>',
            uncommons.length, ' - Number of uncommons<br>',
            rares.length, ' - Number of rares<br>',
            mythics.length, ' - Number of mythics</i></p>');

        for (var j = 1; j <= numPlayers; j++) {
            for (var k = 1; k <=3; k++) {
                count = 0;
                output.push('<p><strong>Player ', j, ', Pack ', k, '</strong></p>',
                    '<table><tr>');
                
                for(var l = 0; l < numC; l++) {
                    while(true) {
                        rand = Math.floor(Math.random()*commons.length);
                        if (chosenc.indexOf(rand) == -1) {
                            chosenc.push(rand);
                            break;
                        }
                    }

                    output.push('<td><a target="_blank" href="http://deckbox.org/mtg/', 
                    commons[rand].replace(" ", "%20"), '"><img src="',
                    commonsi[rand],'"></a></td>');
                    count = count + 1;
                    if (count % 5 == 0) { output.push('</tr><tr>'); }
                }

                for (var m = 0; m < numUn; m++) {
                    while(true) {
                        rand = Math.floor(Math.random()*uncommons.length);
                        if (chosenu.indexOf(rand) == -1) {
                            chosenu.push(rand);
                            break;
                        }
                    }

                    output.push('<td><a target="_blank" href="http://deckbox.org/mtg/', 
                    uncommons[rand].replace(" ", "%20"), '"><img src="',
                    uncommonsi[rand],'"></a></td>');

                    count = count + 1;
                    if (count % 5 == 0) { output.push('</tr><tr>'); }
                }

                for (var n = 0; n < numR; n++) {
                    if (Math.floor(Math.random()*8 != 1)) {
                        while(true) {
                            rand = Math.floor(Math.random()*rares.length);
                            if (chosenr.indexOf(rand) == -1) {
                                chosenr.push(rand);
                                break;
                            }
                        }

                        output.push('<td><a target="_blank" href="http://deckbox.org/mtg/', 
                        rares[rand].replace(" ", "%20"), '"><img src="',
                        raresi[rand],'"></a></td>');
                    } else {
                        while(true) {
                            rand = Math.floor(Math.random()*mythics.length);
                            if (chosenm.indexOf(rand) == -1) {
                                chosenm.push(rand);
                                break;
                            }
                        }

                        output.push('<td><a target="_blank" href="http://deckbox.org/mtg/', 
                        mythics[rand].replace(" ", "%20"), '"><img src="',
                        mythicsi[rand],'"></a></td>');
                    }

                    count = count + 1;
                    if (count % 5 == 0) { output.push('</tr><tr>'); }
                }

                output.push('</tr></table>');
            }
        }

        document.getElementById('out').innerHTML = output.join('');
    };

    reader.readAsText(file);
  }
  
  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
    </body>
</html>

Last edited by Avon (2013-06-28 17:14:19)

Re: Inventory Draft

Awesome idea!  Personally I think mythics should be the same rarity as a real pack (I think it's like 1/12 or something?).  Looks like I might have to actually put my commons and uncommons in my inventory....

Re: Inventory Draft

vanko wrote:

...I think mythics should be the same rarity as a real pack (I think it's like 1/12 or something?).

That's the kind of information I am looking for. Is it guaranteed 1 pack out of 12 has a mythic? Or should I weigh the probability so that mythics are less likely?

Re: Inventory Draft

Paul_K wrote:

according to wizard's formula mythics are 1/8, rares are 7/8.

This is a good rule of thumb, and probably perfect for this situation.  If you want packs to match sealed packs rarity-wise, mythics should be replace rares about 1/8th of the time.  The exact distribution changes very slightly from set to set, but it is always very close to 1/8.*

Since timeshifted stuff is all from earlier sets, any way you can assign each timeshifted card the rarity from its first printing?  If not, it may be better to exclude timeshifted cards entirely than slot them all as rare. 

I'd suggest excluding any card worth more than $X, so your beta timewalk doesn't get randomly picked.  It'd make it kind of like a reject rare draft (which is quite fun actually). 

One other suggestion, could the app work off of tradelists rather than inventory?  That way you don't have to draft something from an existing deck, and we know it is all stuff we're happy to part with. 


*  Just FYI, you can figure out the exact proportion in a set like this.  Count all the rares in a set, e.g. 53 in GTC.  Count all the mythics, e.g. 15 in GTC.  Double all the rares since they get printed twice on a sheet, e.g. 106 in GTC.  Add rares & mythics & divide by mythics, e.g. 15/(15+106) = 12.39% of the rare slots with have a mythic in GTC.  12.39% is very close to 12.5% of 1/8.  DGM is slightly different because each sheet have shock lands too, but otherwise the math works for any set.

Re: Inventory Draft

I could be wrong but I think he meant for this to be like a cube draft, you just play with the cards (instead of giving them up and keeping the ones you draft), so you don't have to worry about losing cards you want to keep.

Re: Inventory Draft

Thanks for the help everyone! Yes, I was picturing this behaving like a cube draft only your entire collection is the card pool. I'm not opposed to letting my friends keep what they draft but that would suck if my beta Timewalk got drafted away wink. I love the idea of setting a value limit. Sounds like a great way to host extremely cheap drafts and get rid of cards for a couple candy bar's worth of change.

This already works with your tradelist as well. You feed it the file you export from Deckbox. Go to either your inventory or tradelist, hover over "View" and select Export. Be sure to include the Rarity and Image URL columns. (PSA - It's a good idea to do this from time to time to back up your virtual collection in case Deckbox ever goes down again).

I still have to develop the user interface for it. Right now you have to run it from a command prompt. Once I wrap it up, I'll share it with everyone who would like a copy.

Re: Inventory Draft

I would like to give this a try this week. The amount of work is a bit steep though. I would want my cards sleeved and that's 45 cards per person to pull out of storage, sleeve, and then return to storage post game. Would it be too much to ask each player bring 45 random cards for their packs as chosen by this program? I can provide different colored sleeves for each person so that your cards will be appropriately returned at the conclusion of the draft. If the program chooses a card you do not want to bring (beta Timewalk), I can also provide a proxy or you can give the selection a re-spin.

During the draft, you would end up with a rainbow of different colored sleeves so, maybe that gives you an unfair advantage (marked cards) but so does everyone else. Please let me know your thoughts. If no one is willing to make some "packs" I can make them all (but I won't like it!)

Re: Inventory Draft

It would be interesting what would get pulled from my collection wink

However, I can't guarantee my availability for anything in the near future sad

Re: Inventory Draft

I'm totally down!

Re: Inventory Draft

When is a good time for everyone? Thurs/Fri night?

If you're willing to help, I need a CSV file of your inventory.

  • Click inventory, hover over View and Hit Export

http://i.imgur.com/jaUBCQt.png

  • Make sure you select Rarity and Image URL options

http://i.imgur.com/AiGo1WO.png

  • Email the file to me gwc6518[AT]rit[DOT]edu, and I will send back an HTML file with a visual spoiler with links to the cards to be provided.

I would provide the program instead but it can only be run from a command prompt and needs Java to be added to your Environment Variables and etc. etc. too complicated...

I can't wait to see what we get from Paul and skyth's pools. At 103,095 cards and 33,151 cards in inventory, there are sure to be some wacky interactions.

If you don't want to pull from inventory, you can do the same steps above with your tradelist.

Re: Inventory Draft

I'm gonna have to put my commons and uncommons online so...I'll get back to you in a while haha.  If I don't have it up in time, I will gladly come over early and help you find/sleeve cards in exchange for borrowing a draft set, but I'll try to get mine up tonight.

Re: Inventory Draft

OK, I wrapped up the first attempt of this program and added all the information in the top of the page. This is some of the ugliest code I have ever written but it seems to work so ... meh.

Here are some thoughts and notes:

  • The draft selection only executes once and as soon as you choose the appropriate file. Refresh the page to redo.

  • It is possible to get duplicate cards if you have duplicates of varying edition, condition, etc. (e.g. an M13 Oblivion Ring and an M12 Oblivion Ring could be chosen but two M13 Oblivion Ring is not possible)

  • The generated page is volatile! If you close the page, use the back button, or navigate away from what was generated in any fashion, the information will be lost forever. Save a copy of the page if you like what was generated.

  • Special rarity cards are not included (e.g. Timeshifted)

  • Cards from Planechase and Vanguard could be included. I don't have them in my inventory so I didn't even think about it.

  • Mythics are chosen 12.5% of the time.

  • There is no error handling. If you use incorrect input, the page just becomes unresponsive. You can use Chrome's debugger (right-click Inspect) to see what's up or just tell me about it here.

  • Each card links to Deckbox and opens in a new tab/window.

  • The statistics that are generated at the top of the page tell you how many unique copies of cards are in your collection.