Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Precision attribute to Normal Distribution Data Type.
- Loading branch information
aevans84
committed
Mar 28, 2016
1 parent
f48960a
commit 2d5b996
Showing
8 changed files
with
220 additions
and
202 deletions.
There are no files selected for viewing
223 changes: 113 additions & 110 deletions
223
plugins/dataTypes/NormalDistribution/NormalDistribution.class.php
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 |
---|---|---|
@@ -1,110 +1,113 @@ | ||
<?php | ||
|
||
/** | ||
* @author Ben Keen <ben.keen@gmail.com> | ||
* @package DataTypes | ||
*/ | ||
class DataType_NormalDistribution extends DataTypePlugin { | ||
|
||
/**#@+ | ||
* @access protected | ||
*/ | ||
protected $isEnabled = true; | ||
protected $dataTypeName = "Standard Normal Distribution"; | ||
protected $dataTypeFieldGroup = "math"; | ||
protected $dataTypeFieldGroupOrder = 10; | ||
protected $jsModules = array("NormalDistribution.js"); | ||
protected $randMax = null; | ||
|
||
|
||
public function generate($generator, $generationContextData) { | ||
$mean = (float) $generationContextData["generationOptions"]["mean"]; | ||
$stddev = (float) $generationContextData["generationOptions"]["stddev"]; | ||
|
||
return array( | ||
"display" => $this->gauss_ms($mean, $stddev) | ||
); | ||
} | ||
|
||
|
||
public function getRowGenerationOptionsUI($generator, $postdata, $colNum, $numCols) { | ||
if ((empty($postdata["dtOptionMean_$colNum"]) && $postdata["dtOptionMean_$colNum"] !== "0") || | ||
(empty($postdata["dtOptionSigma_$colNum"]) && $postdata["dtOptionSigma_$colNum"] !== "0")) { | ||
return false; | ||
} | ||
$this->randMax = (float) getrandmax(); | ||
|
||
return array( | ||
"mean" => $postdata["dtOptionMean_$colNum"], | ||
"stddev" => $postdata["dtOptionSigma_$colNum"] | ||
); | ||
} | ||
|
||
public function getRowGenerationOptionsAPI($generator, $json, $numCols) { | ||
$this->randMax = (float) getrandmax(); | ||
|
||
return array( | ||
"mean" => $json->settings->mean, | ||
"stddev" => $json->settings->sigma | ||
); | ||
} | ||
|
||
public function getOptionsColumnHTML() { | ||
$options =<<< END | ||
<label for="dtOptionMean_%ROW%">{$this->L["mean"]}</label> | ||
<input type="text" name="dtOptionMean_%ROW%" id="dtOptionMean_%ROW%" style="width: 30px" value="0" /> | ||
<label for="dtOptionSigma_%ROW%">{$this->L["standard_deviation"]}</label> | ||
<input type="text" name="dtOptionSigma_%ROW%" id="dtOptionSigma_%ROW%" style="width: 30px" value="1" /> | ||
END; | ||
|
||
return $options; | ||
} | ||
|
||
public function getDataTypeMetadata() { | ||
return array( | ||
"SQLField" => "varchar(100)" | ||
); | ||
} | ||
|
||
// returns random number using mt_rand() with a flat distribution from -1 to 1 inclusive | ||
public function random_PN() { | ||
return (2.0 * $this->random_0_1()) - 1.0; | ||
} | ||
|
||
public function random_0_1() { | ||
return (float) mt_rand() / (float) mt_getrandmax() ; | ||
} | ||
|
||
public function gauss() { | ||
static $useExists = false; | ||
static $useValue; | ||
|
||
if ($useExists) { | ||
// Use value from a previous call to this function | ||
$useExists = false; | ||
return $useValue; | ||
} else { | ||
// Polar form of the Box-Muller transformation | ||
$w = 2.0 ; | ||
while (($w >= 1.0) || ($w == 0.0)) { | ||
$x = $this->random_PN(); | ||
$y = $this->random_PN(); | ||
$w = ($x * $x) + ($y * $y); | ||
} | ||
$w = sqrt((-2.0 * log($w)) / $w); | ||
|
||
// Set value for next call to this function | ||
$useValue = $y * $w; | ||
$useExists = true; | ||
|
||
return $x * $w; | ||
} | ||
} | ||
|
||
public function gauss_ms($mean, $stddev) { | ||
// Adjust our gaussian random to fit the mean and standard deviation | ||
// The division by 4 is an arbitrary value to help fit the distribution | ||
// within our required range, and gives a best fit for $stddev = 1.0 | ||
return $this->gauss() * ($stddev / 4) + $mean; | ||
} | ||
} | ||
<?php | ||
/** | ||
* @author Ben Keen <ben.keen@gmail.com> | ||
* @package DataTypes | ||
*/ | ||
class DataType_NormalDistribution extends DataTypePlugin { | ||
|
||
/**#@+ | ||
* @access protected | ||
*/ | ||
protected $isEnabled = true; | ||
protected $dataTypeName = "Standard Normal Distribution"; | ||
protected $dataTypeFieldGroup = "math"; | ||
protected $dataTypeFieldGroupOrder = 10; | ||
protected $jsModules = array("NormalDistribution.js"); | ||
protected $randMax = null; | ||
|
||
|
||
public function generate($generator, $generationContextData) { | ||
$mean = (float) $generationContextData["generationOptions"]["mean"]; | ||
$stddev = (float) $generationContextData["generationOptions"]["stddev"]; | ||
$precision = (integer) $generationContextData["generationOptions"]["precision"]; | ||
return array( | ||
"display" => round($this->gauss_ms($mean, $stddev), $precision, PHP_ROUND_HALF_UP) | ||
); | ||
} | ||
|
||
|
||
public function getRowGenerationOptionsUI($generator, $postdata, $colNum, $numCols) { | ||
if ((empty($postdata["dtOptionMean_$colNum"]) && $postdata["dtOptionMean_$colNum"] !== "0") || | ||
(empty($postdata["dtOptionSigma_$colNum"]) && $postdata["dtOptionSigma_$colNum"] !== "0")) { | ||
return false; | ||
} | ||
$this->randMax = (float) getrandmax(); | ||
|
||
return array( | ||
"mean" => $postdata["dtOptionMean_$colNum"], | ||
"stddev" => $postdata["dtOptionSigma_$colNum"], | ||
"precision" => $postdata["dtOptionPrecision_$colNum"] | ||
); | ||
} | ||
|
||
public function getRowGenerationOptionsAPI($generator, $json, $numCols) { | ||
$this->randMax = (float) getrandmax(); | ||
|
||
return array( | ||
"mean" => $json->settings->mean, | ||
"stddev" => $json->settings->sigma, | ||
"precision" => $json->settings->precision | ||
); | ||
} | ||
|
||
public function getOptionsColumnHTML() { | ||
$options =<<< END | ||
<label for="dtOptionMean_%ROW%">{$this->L["mean"]}</label> | ||
<input type="text" name="dtOptionMean_%ROW%" id="dtOptionMean_%ROW%" style="width: 30px" value="0" /> | ||
<label for="dtOptionSigma_%ROW%">{$this->L["standard_deviation"]}</label> | ||
<input type="text" name="dtOptionSigma_%ROW%" id="dtOptionSigma_%ROW%" style="width: 30px" value="1" /> | ||
<label for="dtOptionPrecision_%ROW%" title="Number of decimal places.">{$this->L["precision"]}</label> | ||
<input type="text" name="dtOptionPrecision_%ROW%" id="dtOptionPrecision_%ROW%" style="width: 30px" value="0" /> | ||
END; | ||
|
||
return $options; | ||
} | ||
|
||
public function getDataTypeMetadata() { | ||
return array( | ||
"SQLField" => "varchar(100)" | ||
); | ||
} | ||
|
||
// returns random number using mt_rand() with a flat distribution from -1 to 1 inclusive | ||
public function random_PN() { | ||
return (2.0 * $this->random_0_1()) - 1.0; | ||
} | ||
|
||
public function random_0_1() { | ||
return (float) mt_rand() / (float) mt_getrandmax() ; | ||
} | ||
|
||
public function gauss() { | ||
static $useExists = false; | ||
static $useValue; | ||
|
||
if ($useExists) { | ||
// Use value from a previous call to this function | ||
$useExists = false; | ||
return $useValue; | ||
} else { | ||
// Polar form of the Box-Muller transformation | ||
$w = 2.0 ; | ||
while (($w >= 1.0) || ($w == 0.0)) { | ||
$x = $this->random_PN(); | ||
$y = $this->random_PN(); | ||
$w = ($x * $x) + ($y * $y); | ||
} | ||
$w = sqrt((-2.0 * log($w)) / $w); | ||
|
||
// Set value for next call to this function | ||
$useValue = $y * $w; | ||
$useExists = true; | ||
|
||
return $x * $w; | ||
} | ||
} | ||
|
||
public function gauss_ms($mean, $stddev) { | ||
// Adjust our gaussian random to fit the mean and standard deviation | ||
// The division by 4 is an arbitrary value to help fit the distribution | ||
// within our required range, and gives a best fit for $stddev = 1.0 | ||
return $this->gauss() * ($stddev / 4) + $mean; | ||
} | ||
} |
152 changes: 79 additions & 73 deletions
152
plugins/dataTypes/NormalDistribution/NormalDistribution.js
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 |
---|---|---|
@@ -1,74 +1,80 @@ | ||
/*global $:false*/ | ||
define([ | ||
"manager", | ||
"constants", | ||
"lang", | ||
"generator" | ||
], function(manager, C, L, generator) { | ||
|
||
"use strict"; | ||
|
||
/** | ||
* @name NormalDistribution | ||
* @description JS code for the NormalDistribution Data Type. | ||
* @see DataType | ||
* @namespace | ||
*/ | ||
|
||
var MODULE_ID = "data-type-NormalDistribution"; | ||
var LANG = L.dataTypePlugins.NormalDistribution; | ||
var subscriptions = {}; | ||
|
||
var _init = function() { | ||
}; | ||
|
||
var _saveRow = function(rowNum) { | ||
return { | ||
"mean": $("#dtOptionMean_" + rowNum).val(), | ||
"sigma": $("#dtOptionSigma_" + rowNum).val() | ||
}; | ||
}; | ||
|
||
var _loadRow = function(rowNum, data) { | ||
return { | ||
execute: function() { | ||
$("#dtOptionMean_" + rowNum).val(data.mean); | ||
$("#dtOptionSigma_" + rowNum).val(data.sigma); | ||
}, | ||
isComplete: function() { return $("#dtOptionSigma_" + rowNum).length > 0; } | ||
}; | ||
}; | ||
|
||
var _validate = function(rows) { | ||
var visibleProblemRows = []; | ||
var problemFields = []; | ||
for (var i=0; i<rows.length; i++) { | ||
var currMean = $("#dtOptionMean_" + rows[i]); | ||
var currSigma = $("#dtOptionSigma_" + rows[i]); | ||
|
||
var visibleRowNum = generator.getVisibleRowOrderByRowNum(rows[i]); | ||
if ($.trim(currMean.val()) === "" || $.trim(currSigma.val()) === "") { | ||
visibleProblemRows.push(visibleRowNum); | ||
|
||
if ($.trim(currMean.val()) === "") { | ||
problemFields.push(currMean); | ||
} | ||
if ($.trim(currSigma.val()) === "") { | ||
problemFields.push(currSigma); | ||
} | ||
} | ||
} | ||
var errors = []; | ||
if (visibleProblemRows.length) { | ||
errors.push({ els: problemFields, error: LANG.incomplete_fields + " <b>" + visibleProblemRows.join(", ") + "</b>"}); | ||
} | ||
return errors; | ||
}; | ||
|
||
manager.registerDataType(MODULE_ID, { | ||
init: _init, | ||
validate: _validate, | ||
saveRow: _saveRow, | ||
loadRow: _loadRow | ||
}); | ||
/*global $:false*/ | ||
define([ | ||
"manager", | ||
"constants", | ||
"lang", | ||
"generator" | ||
], function(manager, C, L, generator) { | ||
|
||
"use strict"; | ||
|
||
/** | ||
* @name NormalDistribution | ||
* @description JS code for the NormalDistribution Data Type. | ||
* @see DataType | ||
* @namespace | ||
*/ | ||
|
||
var MODULE_ID = "data-type-NormalDistribution"; | ||
var LANG = L.dataTypePlugins.NormalDistribution; | ||
var subscriptions = {}; | ||
|
||
var _init = function() { | ||
}; | ||
|
||
var _saveRow = function(rowNum) { | ||
return { | ||
"mean": $("#dtOptionMean_" + rowNum).val(), | ||
"sigma": $("#dtOptionSigma_" + rowNum).val(), | ||
"precision": $("#dtOptionPrecision_" + rowNum).val() | ||
}; | ||
}; | ||
|
||
var _loadRow = function(rowNum, data) { | ||
return { | ||
execute: function() { | ||
$("#dtOptionMean_" + rowNum).val(data.mean); | ||
$("#dtOptionSigma_" + rowNum).val(data.sigma); | ||
$("#dtOptionPrecision_" + rowNum).val(data.precision); | ||
}, | ||
isComplete: function() { return $("#dtOptionSigma_" + rowNum).length > 0; } | ||
}; | ||
}; | ||
|
||
var _validate = function(rows) { | ||
var visibleProblemRows = []; | ||
var problemFields = []; | ||
for (var i=0; i<rows.length; i++) { | ||
var currMean = $("#dtOptionMean_" + rows[i]); | ||
var currSigma = $("#dtOptionSigma_" + rows[i]); | ||
var currPrecision = $("#dtOptionPrecision_" + rows[i]); | ||
|
||
var visibleRowNum = generator.getVisibleRowOrderByRowNum(rows[i]); | ||
if ($.trim(currMean.val()) === "" || $.trim(currSigma.val()) === "") { | ||
visibleProblemRows.push(visibleRowNum); | ||
|
||
if ($.trim(currMean.val()) === "") { | ||
problemFields.push(currMean); | ||
} | ||
if ($.trim(currSigma.val()) === "") { | ||
problemFields.push(currSigma); | ||
} | ||
if ($.trim(currPrecision.val()) === "") { | ||
problemFields.push(currPrecision); | ||
} | ||
} | ||
} | ||
var errors = []; | ||
if (visibleProblemRows.length) { | ||
errors.push({ els: problemFields, error: LANG.incomplete_fields + " <b>" + visibleProblemRows.join(", ") + "</b>"}); | ||
} | ||
return errors; | ||
}; | ||
|
||
manager.registerDataType(MODULE_ID, { | ||
init: _init, | ||
validate: _validate, | ||
saveRow: _saveRow, | ||
loadRow: _loadRow | ||
}); | ||
}); |
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
Oops, something went wrong.