Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dev: Add new column 'seed' to dynamic survey table
- Loading branch information
1 parent
9c9a64c
commit 2a7f83c
Showing
5 changed files
with
126 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?php | ||
|
||
namespace ls\mersenne; | ||
|
||
/** | ||
* Get seed for this answer | ||
* If there is no seed create a new one | ||
* @param int $surveyId | ||
* @param boolean $preview | ||
* @return int | ||
*/ | ||
function getSeed($surveyId, $preview) | ||
{ | ||
$columnNames = \SurveyDynamic::model($surveyId)->getTableSchema()->getColumnNames(); | ||
traceVar($columnNames); | ||
// Get columns | ||
// Check if we have seed column | ||
// Yes: check value | ||
// have value, use it | ||
// no value, generate new seed | ||
// No: create column | ||
// generate seed | ||
// insert seed | ||
// Use seed to instantiate twister | ||
} | ||
|
||
/** | ||
* Shuffle with seed | ||
* @param array $arr | ||
* @param $seed | ||
* @return array | ||
*/ | ||
function shuffle($arr, $seed=-1) | ||
{ | ||
if ( $seed == -1 ) return $arr; | ||
$mt = new MersenneTwister($seed); | ||
$new = $arr; | ||
for ($i = count($new) - 1; $i > 0; $i--) | ||
{ | ||
$j = $mt->getNext(0,$i); | ||
$tmp = $new[$i]; | ||
$new[$i] = $new[$j]; | ||
$new[$j] = $tmp; | ||
} | ||
return $new; | ||
} | ||
|
||
/** | ||
* Custom random algorithm to get consistent behaviour between PHP versions. | ||
* | ||
* Copied from: http://www.dr-chuck.com/csev-blog/2015/09/a-mersenne_twister-implementation-in-php/ | ||
*/ | ||
class MersenneTwister | ||
{ | ||
private $state = array (); | ||
private $index = 0; | ||
|
||
public function __construct($seed = null) { | ||
if ($seed === null) | ||
$seed = mt_rand(); | ||
|
||
$this->setSeed($seed); | ||
} | ||
|
||
public function setSeed($seed) { | ||
$this->state[0] = $seed & 0xffffffff; | ||
|
||
for ($i = 1; $i < 624; $i++) { | ||
$this->state[$i] = (((0x6c078965 * ($this->state[$i - 1] ^ ($this->state[$i - 1] >> 30))) + $i)) & 0xffffffff; | ||
} | ||
|
||
$this->index = 0; | ||
} | ||
|
||
private function generateTwister() { | ||
for ($i = 0; $i < 624; $i++) { | ||
$y = (($this->state[$i] & 0x1) + ($this->state[$i] & 0x7fffffff)) & 0xffffffff; | ||
$this->state[$i] = ($this->state[($i + 397) % 624] ^ ($y >> 1)) & 0xffffffff; | ||
|
||
if (($y % 2) == 1) { | ||
$this->state[$i] = ($this->state[$i] ^ 0x9908b0df) & 0xffffffff; | ||
} | ||
} | ||
} | ||
|
||
public function getNext($min = null, $max = null) { | ||
if (($min === null && $max !== null) || ($min !== null && $max === null)) | ||
throw new Exception('Invalid arguments'); | ||
|
||
if ($this->index === 0) { | ||
$this->generateTwister(); | ||
} | ||
|
||
$y = $this->state[$this->index]; | ||
$y = ($y ^ ($y >> 11)) & 0xffffffff; | ||
$y = ($y ^ (($y << 7) & 0x9d2c5680)) & 0xffffffff; | ||
$y = ($y ^ (($y << 15) & 0xefc60000)) & 0xffffffff; | ||
$y = ($y ^ ($y >> 18)) & 0xffffffff; | ||
|
||
$this->index = ($this->index + 1) % 624; | ||
|
||
if ($min === null && $max === null) | ||
return $y; | ||
|
||
$range = abs($max - $min); | ||
|
||
return min($min, $max) + ($y % ($range + 1)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters