rectest/scripts/set/RandomGroupedSet.js

115 lines
2.7 KiB
JavaScript

/**
* Represents a set that is randomized each time the first element is reached.
* The set will loop back to the first element until the required number of
* samples are satisfied.
*
* Note that this means that, should the sample size be larger than the number
* of elements in the set, the set will be randomized only for each iteration,
* which may not be what you want for a truely random sample set.
*/
rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
.implement( rectest.set.Set )
.extend(
{
/**
* Number of samples remaining
* @var {number}
*/
'private _samplesRemain': 0,
/**
* Set to operate on
* @var {Array.<string>}
*/
'private _set': [],
/**
* Set length
* @var {number}
*/
'private _setLength': 0,
/**
* Current set position
* @var {number}
*/
'private _setPos': 0,
__construct: function( base_set, sample_size )
{
this._set = base_set;
this._samplesRemain = +sample_size || -1;
this._reset();
},
/**
* Randomizes a set using the Fisher-Yates shuffle algorithm
*
* @param {Array} set set to sort
*/
'virtual protected randomizeSet': function( set )
{
var i = set.length;
// simply prevent an infinite loop below
if ( i === 0 )
{
return set;
}
// simply loop through each element in the set, swapping each with a
// random index
while ( --i )
{
var r = Math.floor( Math.random() * ( i + 1 ) );
set[ i ] = [ set[ r ], ( set[ r ] = set[ i ] ) ][ 0 ];
}
return set;
},
/**
* Retrieve the next element in the set
*
* @return {string} next element in set
*/
'public getNextElement': function()
{
// return null once we have returned all of the requested samples
// (intentionally a 0 check, as this will be negative for an
// infinite number of samples)
if ( this._samplesRemain-- === 0 )
{
return null;
}
// reset once we're at the end
if ( this._setPos === this._setLength )
{
this._reset();
}
// return element from set (do not shift/pop, since we may need to
// repeatedly iterate through this list)
return this._set[ this._setPos++ ];
},
'private _reset': function()
{
this._setPos = 0;
this._set = this.randomizeSet( this._set );
this._setLength = this._set.length;
},
'protected getSampleSize': function()
{
return this._samplesRemain;
}
} );