require './helpers' should = require 'should' async = require 'async' {BattleQueue} = require('../server/queue') redis = require('../server/redis') ratings = require('../server/ratings') alts = require('../server/alts') async = require('async') describe 'BattleQueue', -> it 'should be empty by default', -> new BattleQueue().should.have.length(0) describe '#add', -> it 'queues a new player', -> queue = new BattleQueue() queue.add('derp', 'derp', {}) queue.should.have.length 1 it 'queues two players', -> queue = new BattleQueue() queue.add('batman', 'batman', {}) queue.add('superman', 'superman', {}) queue.should.have.length 2 it 'cannot queue the same player twice', -> queue = new BattleQueue() queue.add('batman', 'batman', {}) queue.add('batman', 'batman', {}) queue.should.have.length 1 it 'cannot queue falsy references', -> queue = new BattleQueue() queue.add(null, null, {}) queue.add(false, false, {}) queue.add(undefined, undefined, {}) queue.should.have.length 0 describe '#remove', -> it 'can dequeue old players', -> queue = new BattleQueue() player = 'abc' queue.add(player, player, {}) queue.remove(player) queue.size().should.equal 0 it "can take an array of players", -> queue = new BattleQueue() player1 = 'abc' player2 = 'def' queue.add(player1, player1, {}) queue.add(player2, player2, {}) queue.remove([ player1, player2 ]) queue.should.have.length 0 describe '#queuedPlayers', -> it 'returns the players who are queued', -> queue = new BattleQueue() dude = 'dude' queue.add(dude) queue.queuedPlayers().should.containEql(dude) queue.queuedPlayers().should.have.length 1 describe '#hasRecentlyMatched', -> it "returns false if two players have not queued", -> queue = new BattleQueue() queue.hasRecentlyMatched("p1", "p2").should.be.false it "returns true if two players have queued", -> queue = new BattleQueue() queue.addRecentMatch("p1", "p2") queue.hasRecentlyMatched("p1", "p2").should.be.true it "is not affected by ordering", -> queue = new BattleQueue() queue.addRecentMatch("p1", "p2") queue.hasRecentlyMatched("p1", "p2").should.be.true queue.hasRecentlyMatched("p2", "p1").should.be.true it "returns false if 30 minutes has passed since two players have queued", -> queue = new BattleQueue() queue.addRecentMatch("p1", "p2") queue.hasRecentlyMatched("p1", "p2").should.be.true @clock.tick(31 * 60 * 1000) queue.hasRecentlyMatched("p1", "p2").should.be.false describe '#pairPlayers', -> it 'takes players out of the queue', (done) -> queue = new BattleQueue() queue.add('batman') queue.add('superman') queue.pairPlayers -> queue.queuedPlayers().should.be.empty done() it 'leaves one person out if the queue length is odd', (done) -> queue = new BattleQueue() queue.add('batman') queue.add('superman') queue.add('flash') queue.pairPlayers -> queue.queuedPlayers().should.have.length 1 done() it 'returns an array of pairs', (done) -> queue = new BattleQueue() queue.add('batman', 'Bruce Wayne') queue.add('superman', 'Clark Kent') queue.add('flash', 'Wally West') queue.add('spiderman', 'Peter Parker') queue.pairPlayers (err, results) -> should.not.exist(err) should.exist(results) results.should.be.instanceOf(Array) results.should.have.length(2) done() it 'returns id/name/team/ratingkeyobjects', (done) -> queue = new BattleQueue() queue.add('batman', 'Bruce Wayne', [], 'bat') queue.add('superman', 'Clark Kent', [], 'supes') queue.pairPlayers (err, results) -> should.not.exist(err) should.exist(results) results.should.eql [[ {id: 'batman', name: 'Bruce Wayne', team: [], ratingKey: 'bat' } {id: 'superman', name: 'Clark Kent', team: [], ratingKey: 'supes' } ]] done() it "returns an array of pairs in the order of their rating", (done) -> scores = [["batman", 1], ["superman", 4], ["flash", 3], ["spiderman", 2]] callbacks = for [player, score] in scores ratings.setRating.bind(ratings, player, score) async.parallel callbacks, -> queue = new BattleQueue() queue.add(pair[0]) for pair in scores queue.pairPlayers (err, results) -> should.not.exist(err) should.exist(results) results.should.be.instanceOf(Array) results.should.have.length(2) results = results.map (result) -> [result[0].id, result[1].id] results.should.eql [[ "batman", "spiderman" ] [ "flash", "superman" ]] done() it "does not match the same players twice", (done) -> scores = [["batman", 1], ["superman", 4], ["flash", 3], ["spiderman", 2]] callbacks = for [player, score] in scores ratings.setRating.bind(ratings, player, score) async.parallel callbacks, -> queue = new BattleQueue() queue.add(pair[0]) for pair in scores queue.pairPlayers (err, results) -> should.not.exist(err) results = results.map (result) -> [result[0].id, result[1].id] results.should.eql [[ "batman", "spiderman" ] [ "flash", "superman" ]] # now perform round two: Should get different results queue.add(pair[0]) for pair in scores queue.pairPlayers (err, results) -> should.not.exist(err) results = results.map (result) -> [result[0].id, result[1].id] results.should.eql [[ "batman", "flash" ] [ "spiderman", "superman" ]] done() it "does not match players with a large rating gap until it expands", (done) -> scores = [["batman", 900], ["superman", 1005]] callbacks = for [player, score] in scores ratings.setRating.bind(ratings, player, score) async.parallel callbacks, -> queue = new BattleQueue() queue.add(pair[0]) for pair in scores # first run - no matches should be found queue.pairPlayers (err, results) -> should.not.exist(err) results.should.have.length 0 # second run - should have found a match queue.pairPlayers (err, results) -> should.not.exist(err) results.should.have.length 1 done() it "returns a different ordering for alts ratings", (done) -> users = [ ["batman", "Bruce Wayne", 1, 1] ["superman", "Clark Kent", 4, 4] ["flash", "Wally West", 3, 2] ["spiderman", "Peter Parker", 2, 3] ] ratingTasks = [] for user in users # non-alt ratingTasks.push ratings.setRating.bind(null, user[0], user[2]) # alt altId = alts.uniqueId(user[0], user[1]) ratingTasks.push ratings.setRating.bind(this, altId, user[3]) async.series ratingTasks, -> queue = new BattleQueue() queue.add(user[0]) for user in users queue.pairPlayers (err, results) -> should.not.exist(err) results = results.map((result) -> [result[0].id, result[1].id]) results.should.eql [[ "batman", "spiderman" ], [ "flash", "superman" ]] # now test alts getting added queue.add(user[0], user[1], null, alts.uniqueId(user[0], user[1])) for user in users queue.pairPlayers (err, results) -> should.not.exist(err) results = results.map((result) -> [result[0].id, result[1].id]) results.should.eql [["batman", "flash"], ["spiderman", "superman"]] done()