Added RandomAllInclusiveSet (ideal algorithm for random testing)
parent
31b7fb8e44
commit
02db399e56
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* Represents a set that randomizes all elements of an entire predicted set,
|
||||||
|
* ensuring that repeat sets are less predictable.
|
||||||
|
*
|
||||||
|
* This algorithm works by first repeating the given set S the necessary number
|
||||||
|
* of times in order to produce a new set S' that contains at least one element
|
||||||
|
* for the requested sample size. S' is then randomized in its entirety.
|
||||||
|
*
|
||||||
|
* See also RandomGroupedSet.
|
||||||
|
*/
|
||||||
|
rectest.set.RandomAllInclusiveSet = Class( 'RandomAllInclusiveSet' )
|
||||||
|
.extend( rectest.set.RandomGroupedSet,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Randomizes an entire set large enough to encompass the requested sample
|
||||||
|
* size
|
||||||
|
*
|
||||||
|
* The actual array randomization algorithm is inherited from the parent.
|
||||||
|
*
|
||||||
|
* @param {Array} set set to randomize
|
||||||
|
*
|
||||||
|
* @return {Array} randomized set
|
||||||
|
*/
|
||||||
|
'override protected randomizeSet': function( set )
|
||||||
|
{
|
||||||
|
var samples = this.getSampleSize();
|
||||||
|
|
||||||
|
// this algorithm will work only if we know how many samples are desired
|
||||||
|
if ( samples < 1 )
|
||||||
|
{
|
||||||
|
throw Error(
|
||||||
|
"RandomAllInclusiveSet can only be used with sets of " +
|
||||||
|
"known length; desired sample size is unknown"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing we can do with an empty set (avoid the division by 0 and just
|
||||||
|
// bail out)
|
||||||
|
if ( set.length === 0 )
|
||||||
|
{
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the super method with the set repeated N times, where N is the
|
||||||
|
// minimum number of repeats required to satisfy the requested sample
|
||||||
|
// size (may result in a set larger than the sample size, but that is
|
||||||
|
// fine)
|
||||||
|
return this.__super( this._repeatSet( set,
|
||||||
|
Math.ceil( samples / set.length )
|
||||||
|
) );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively repeats the given set n times
|
||||||
|
*
|
||||||
|
* @param {Array} set set to repeat
|
||||||
|
* @param {number} n number of times to repeat
|
||||||
|
* @param {=Array} s2 destination array (defaults to [] on first iteration)
|
||||||
|
*
|
||||||
|
* @return {Array} s2 after operation is complete
|
||||||
|
*/
|
||||||
|
'private _repeatSet': function( set, n, s2 )
|
||||||
|
{
|
||||||
|
s2 = s2 || [];
|
||||||
|
n = ( isNaN( n ) ) ? 0 : n; // failsafe
|
||||||
|
|
||||||
|
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.push( set[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._repeatSet( set, --n, s2 );
|
||||||
|
}
|
||||||
|
} );
|
|
@ -2,6 +2,10 @@
|
||||||
* Represents a set that is randomized each time the first element is reached.
|
* 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
|
* The set will loop back to the first element until the required number of
|
||||||
* samples are satisfied.
|
* 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' )
|
rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
.implement( rectest.set.Set )
|
.implement( rectest.set.Set )
|
||||||
|
@ -35,48 +39,25 @@ rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
__construct: function( base_set, sample_size )
|
__construct: function( base_set, sample_size )
|
||||||
{
|
{
|
||||||
this._set = base_set;
|
this._set = base_set;
|
||||||
this._setLength = this._set.length;
|
|
||||||
this._samplesRemain = +sample_size || -1;
|
this._samplesRemain = +sample_size || -1;
|
||||||
|
|
||||||
this._reset();
|
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
|
* Randomizes a set using the Fisher-Yates shuffle algorithm
|
||||||
*
|
*
|
||||||
* @param {Array} set set to sort
|
* @param {Array} set set to sort
|
||||||
*/
|
*/
|
||||||
'private _randomizeSet': function( set )
|
'virtual protected randomizeSet': function( set )
|
||||||
{
|
{
|
||||||
var i = set.length;
|
var i = set.length;
|
||||||
|
|
||||||
// simply prevent an infinite loop below
|
// simply prevent an infinite loop below
|
||||||
if ( i === 0 )
|
if ( i === 0 )
|
||||||
{
|
{
|
||||||
return;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simply loop through each element in the set, swapping each with a
|
// simply loop through each element in the set, swapping each with a
|
||||||
|
@ -86,6 +67,8 @@ rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
var r = Math.floor( Math.random() * ( i + 1 ) );
|
var r = Math.floor( Math.random() * ( i + 1 ) );
|
||||||
set[ i ] = [ set[ r ], ( set[ r ] = set[ i ] ) ][ 0 ];
|
set[ i ] = [ set[ r ], ( set[ r ] = set[ i ] ) ][ 0 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,12 +79,6 @@ rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
*/
|
*/
|
||||||
'public getNextElement': function()
|
'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
|
// return null once we have returned all of the requested samples
|
||||||
// (intentionally a 0 check, as this will be negative for an
|
// (intentionally a 0 check, as this will be negative for an
|
||||||
// infinite number of samples)
|
// infinite number of samples)
|
||||||
|
@ -110,6 +87,12 @@ rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
return null;
|
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
|
// return element from set (do not shift/pop, since we may need to
|
||||||
// repeatedly iterate through this list)
|
// repeatedly iterate through this list)
|
||||||
return this._set[ this._setPos++ ];
|
return this._set[ this._setPos++ ];
|
||||||
|
@ -119,6 +102,13 @@ rectest.set.RandomGroupedSet = Class( 'RandomGroupedSet' )
|
||||||
'private _reset': function()
|
'private _reset': function()
|
||||||
{
|
{
|
||||||
this._setPos = 0;
|
this._setPos = 0;
|
||||||
this._randomizeSet( this._set );
|
this._set = this.randomizeSet( this._set );
|
||||||
|
this._setLength = this._set.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'protected getSampleSize': function()
|
||||||
|
{
|
||||||
|
return this._samplesRemain;
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -8,7 +8,7 @@ rectest.set.SetFactory = Class( 'SetFactory',
|
||||||
var sets = rectest.set;
|
var sets = rectest.set;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
null,
|
sets.RandomAllInclusiveSet,
|
||||||
sets.RandomGroupedSet,
|
sets.RandomGroupedSet,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
development purposes -->
|
development purposes -->
|
||||||
<script type="text/javascript" src="scripts/set/Set.js"></script>
|
<script type="text/javascript" src="scripts/set/Set.js"></script>
|
||||||
<script type="text/javascript" src="scripts/set/RandomGroupedSet.js"></script>
|
<script type="text/javascript" src="scripts/set/RandomGroupedSet.js"></script>
|
||||||
|
<script type="text/javascript" src="scripts/set/RandomAllInclusiveSet.js"></script>
|
||||||
<script type="text/javascript" src="scripts/set/SetFactory.js"></script>
|
<script type="text/javascript" src="scripts/set/SetFactory.js"></script>
|
||||||
<script type="text/javascript" src="scripts/TestCase.js"></script>
|
<script type="text/javascript" src="scripts/TestCase.js"></script>
|
||||||
<script type="text/javascript" src="scripts/TestRun.js"></script>
|
<script type="text/javascript" src="scripts/TestRun.js"></script>
|
||||||
|
|
Loading…
Reference in New Issue