diff --git a/public/partials/q.html b/public/partials/q.html
index 83e8b11..e82fb03 100644
--- a/public/partials/q.html
+++ b/public/partials/q.html
@@ -71,8 +71,8 @@
pack
-
-
+
+
diff --git a/src/_.co b/src/_.co
new file mode 100644
index 0000000..73e4671
--- /dev/null
+++ b/src/_.co
@@ -0,0 +1,18 @@
+rand = -> Math.random! * it | 0
+
+module.exports = _ =
+ next: (arr, delta, index) ->
+ length = arr.length
+ index = (index + delta + length) % length # negative modulo
+ arr[index]
+ rand: rand
+ shuffle: (arr) ->
+ # shuffling is the special case where all items are chosen
+ _.choose arr.length, arr
+ choose: (n, arr) ->
+ i = arr.length
+ end = i - n or 1
+ while i > end
+ j = rand i--
+ arr[i, j] = arr[j, i]
+ arr.slice -n
diff --git a/src/bot.co b/src/bot.co
new file mode 100644
index 0000000..8552f7d
--- /dev/null
+++ b/src/bot.co
@@ -0,0 +1,21 @@
+Player = require \./player
+
+nop = ->
+
+class Bot extends Player
+ ->
+ super!
+
+ isBot: true
+ name: \bot
+ send: nop
+
+ sendPack: ->
+ [pack] = @packs
+
+ if pack.length is 1
+ @pick 0 true
+ else
+ process.nextTick @~autopick
+
+module.exports = Bot
diff --git a/src/db.co b/src/db.co
new file mode 100644
index 0000000..a6b6a86
--- /dev/null
+++ b/src/db.co
@@ -0,0 +1,16 @@
+request = require \request
+{rand} = require \./_
+couch = require \../data/couch
+
+module.exports = (data) ->
+ options = {} <<<< couch
+
+ # sequential ids for extreme performance
+ data._id = data.end + rand 1e9 .toString 16 .slice -6
+ options.uri += data._id
+ options.json = data
+
+ console.log options.uri
+ request options, (err, res, body) ->
+ throw err if err
+ console.log body
diff --git a/src/draft.co b/src/draft.co
new file mode 100644
index 0000000..b5003f1
--- /dev/null
+++ b/src/draft.co
@@ -0,0 +1,90 @@
+{EventEmitter} = require \events
+Bot = require \./bot
+Human = require \./human
+db = require \./db
+{next, rand, shuffle} = require \./_
+
+class Draft extends EventEmitter
+ (opts) ->
+ @ <<<< opts
+ @ <<<<
+ delta: -1
+ id: rand 1e9 .toString 16
+ players: []
+ round: 0
+ startTime: Date.now! / 1e3 | 0
+
+ join: (sock) ->
+ {name} = sock
+ for p of @players
+ if p.name is name
+ return p.attach sock
+
+ if @players.length is @seats
+ return p.send \error 'draft full'
+
+ h = new Human sock
+ h.isHost = sock.id is @host
+ @add h
+
+ add: (p) ->
+ @players.push p
+ p.on \pass @~pass
+
+ return if p.isBot
+
+ @meta!
+
+ if p.isHost
+ p.once \start @~start
+ p.emit \start
+
+ meta: ->
+ players = for p of @players
+ { p.name, p.time, packs: p.packs.length }
+ for p of @players
+ p.send \set { players }
+
+ start: ->
+ if @addBots
+ while @players.length < @seats
+ @add new Bot
+
+ shuffle @players
+
+ for p, i of @players
+ p.index = i
+
+ @startRound!
+
+ startRound: ->
+ unless set = @sets[@round++]
+ return @end!
+
+ @delta *= -1
+ @activePacks = @players.length
+
+ for p of @players
+ p.start set
+
+ pass: (pack, index) ->
+ player = next @players, @delta, index
+
+ if pack.length
+ player.receive pack
+ else if !--@activePacks
+ @startRound!
+
+ @meta!
+
+ end: ->
+ console.log \end @id
+
+ data = @{ sets, start: startTime }
+ data.end = Date.now! / 1e3 | 0
+ data.players = for p of @players
+ p{ isBot, picks }
+
+ db data
+
+module.exports = Draft
diff --git a/src/genPack.co b/src/genPack.co
new file mode 100644
index 0000000..086e21b
--- /dev/null
+++ b/src/genPack.co
@@ -0,0 +1,28 @@
+Cards = require \../data/cards
+Sets = require \../data/sets
+{choose, rand} = require \./_
+
+genPack = (setName) ->
+ {common, uncommon, rare, mythic, special} = Sets[setName]
+ mythic or= rare
+ unless rand 8
+ rare = mythic
+
+ pack = [].concat(
+ choose 10 common
+ choose 3 uncommon
+ choose 1 rare
+ )
+
+ switch setName
+ case "Dragon's Maze"
+ special = if rand 22 then <>gate else <>shock
+ fallthrough
+ case 'Time Spiral'
+ index = rand special.length
+ pack.push special[index]
+
+ for name of pack
+ Cards[name]
+
+module.exports = genPack
diff --git a/cards/getCards.co b/src/getCards.co
similarity index 100%
rename from cards/getCards.co
rename to src/getCards.co
diff --git a/cards/getSetNames.co b/src/getSetNames.co
similarity index 100%
rename from cards/getSetNames.co
rename to src/getSetNames.co
diff --git a/src/human.co b/src/human.co
new file mode 100644
index 0000000..189ccfe
--- /dev/null
+++ b/src/human.co
@@ -0,0 +1,28 @@
+Player = require \./player
+
+class Human extends Player
+ (sock) ->
+ super!
+ @attach sock
+
+ isBot: false
+
+ attach: (sock) ->
+ {@name} = sock
+ @send = sock~send
+ @send \set { @main, pack: @packs.0 }
+ sock.on \pick @~pick
+
+ sendPack: ->
+ pack = @packs.0
+
+ if pack.length is 1
+ @pick 0 true
+ else
+ @send \set { pack }
+
+ pick: (index) ->
+ super index
+ @send \add @main[* - 1]
+
+module.exports = Human
diff --git a/src/player.co b/src/player.co
new file mode 100644
index 0000000..e6bc7cb
--- /dev/null
+++ b/src/player.co
@@ -0,0 +1,39 @@
+{EventEmitter} = require \events
+{rand} = require \./_
+genPack = require \./genPack
+
+class Player extends EventEmitter
+ ->
+ @ <<<<
+ picks: []
+ packs: []
+ main: []
+
+ time: 0
+
+ start: (set) ->
+ @picks.push @round = []
+ @receive genPack set
+
+ receive: (pack) ->
+ @packs.push pack
+
+ if @packs.length is 1
+ @sendPack!
+
+ autopick: ->
+ index = rand @packs.0.length
+ @pick index, true
+
+ pick: (index, autopick) ->
+ pack = @packs.shift!
+ [pick] = pack.splice index, 1
+ @main.push pick
+ @round.push { pick.name, autopick }
+
+ if @packs.length
+ @sendPack!
+
+ @emit \pass pack, @index
+
+module.exports = Player
diff --git a/src/router.co b/src/router.co
new file mode 100644
index 0000000..bd96044
--- /dev/null
+++ b/src/router.co
@@ -0,0 +1,25 @@
+Draft = require \./draft
+Sock = require \./sock
+
+drafts = {}
+
+rm = ->
+ delete drafts[@id]
+
+
+router =
+ create: (opts) ->
+ draft = new Draft opts
+ drafts[draft.id] = draft
+ draft.on \end rm
+ draft.id
+ connect: (ws) ->
+ sock = new Sock ws
+ {room} = sock
+
+ if draft = drafts[room]
+ draft.join sock
+ else
+ sock.send \error 'room not found'
+
+module.exports = router
diff --git a/cards/scrape.co b/src/scrape.co
similarity index 100%
rename from cards/scrape.co
rename to src/scrape.co
diff --git a/src/sock.co b/src/sock.co
new file mode 100644
index 0000000..3292c8c
--- /dev/null
+++ b/src/sock.co
@@ -0,0 +1,13 @@
+{EventEmitter} = require \events
+
+class Sock extends EventEmitter
+ (@ws) ->
+ @ <<<< ws.request.query{ id, name, room }
+ ws.on \message @~message
+
+ message: -> @emit ...JSON.parse it
+
+ send: (name, args) ->
+ @ws.send JSON.stringify { name, args }
+
+module.exports = Sock