132 lines
2.9 KiB
JavaScript
132 lines
2.9 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.
|
||
|
*/
|
||
|
rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||
|
.implement( rectest.set.Set )
|
||
|
.extend(
|
||
|
{
|
||
|
/**
|
||
|
* Test case being executed
|
||
|
* @var {TestCase}
|
||
|
*/
|
||
|
'private _case': null,
|
||
|
|
||
|
/**
|
||
|
* 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( test_case, options )
|
||
|
{
|
||
|
this._case = test_case;
|
||
|
this._set = test_case.getSet( options.set );
|
||
|
this._setLength = this._set.length;
|
||
|
this._samplesRemain = +options.samples || -1;
|
||
|
|
||
|
this._reset();
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _repeatSet': function( set, n, s2 )
|
||
|
{
|
||
|
s2 = s2 || [];
|
||
|
|
||
|
var i = set.length;
|
||
|
|
||
|
if ( n === 0 )
|
||
|
{
|
||
|
return s2;
|
||
|
}
|
||
|
|
||
|
// does not matter that we're doing it in reverse, since the set
|
||
|
// will be randomized later
|
||
|
while ( i-- )
|
||
|
{
|
||
|
s2[ i ] = set[ i ];
|
||
|
}
|
||
|
|
||
|
return this._repeatSet( set, --n, s2 );
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Randomizes a set using the Fisher-Yates shuffle algorithm
|
||
|
*
|
||
|
* @param {Array} set set to sort
|
||
|
*/
|
||
|
'private _randomizeSet': function( set )
|
||
|
{
|
||
|
var i = set.length;
|
||
|
|
||
|
// simply prevent an infinite loop below
|
||
|
if ( i === 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 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 ];
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieve the next element in the set
|
||
|
*
|
||
|
* @return {string} next element in set
|
||
|
*/
|
||
|
'public getNextElement': function()
|
||
|
{
|
||
|
// reset once we're at the end
|
||
|
if ( this._setPos === this._setLength )
|
||
|
{
|
||
|
this._reset();
|
||
|
}
|
||
|
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
// 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._randomizeSet( this._set );
|
||
|
}
|
||
|
} );
|