secretsanta/SecretSanta.js
2015-12-12 14:49:20 +01:00

78 lines
2 KiB
JavaScript

var SecretSanta = function () {
this.names = [];
this.blacklists = Object.create( null );
};
SecretSanta.prototype.add = function ( name ) {
if ( this.names.indexOf( name ) !== -1 )
throw new Error( 'Cannot redefine ' + name );
this.names.push( name );
var subapi = { };
subapi.blacklist = function ( other ) {
if ( ! Object.prototype.hasOwnProperty.call( this.blacklists, name ) )
this.blacklists[ name ] = [];
if ( this.blacklists[ name ].indexOf( other ) === -1 )
this.blacklists[ name ].push( other );
return subapi;
}.bind( this );
return subapi;
};
SecretSanta.prototype.generate = function () {
var pairings = Object.create( null );
var candidatePairings = Object.create( null );
this.names.forEach( function ( name ) {
var candidates = _.difference( this.names, name );
if ( Object.prototype.hasOwnProperty.call( this.blacklists, name ) )
candidates = _.difference( candidates, this.blacklists[ name ] );
candidatePairings[ name ] = candidates;
}, this );
var findNextGifter = function () {
var names = Object.keys( candidatePairings );
var minCandidateCount = _.min( names.map( function ( name ) { return candidatePairings[ name ].length; } ) );
var potentialGifters = names.filter( function ( name ) { return candidatePairings[ name ].length === minCandidateCount; } );
return _.sample( potentialGifters );
};
while ( Object.keys( candidatePairings ).length > 0 ) {
var name = findNextGifter();
var pairing = _.sample( candidatePairings[ name ] );
delete candidatePairings[ name ];
Object.keys( candidatePairings ).forEach( function ( name ) {
candidatePairings[ name ] = _.without( candidatePairings[ name ], pairing );
} );
pairings[ name ] = pairing;
}
return pairings;
};