diff --git a/src/Score.php b/src/Score.php index b689255..3426192 100644 --- a/src/Score.php +++ b/src/Score.php @@ -21,7 +21,7 @@ /** * An optional field that represents the outcome of a graded Activity achieved - * by an Agent. + * by an actor. */ class Score implements VersionableInterface, ComparableInterface { @@ -32,7 +32,6 @@ class Score implements VersionableInterface, ComparableInterface * * @var int */ - const DEFAULT_PRECISION = 2; const SCALE_MIN = -1; const SCALE_MAX = 1; /**#@- */ @@ -69,66 +68,38 @@ class Score implements VersionableInterface, ComparableInterface /** * Constructor * - * @param float|array $aRawValue the score value, may also be an array of properties + * @param float|array $aRawValue the raw score value, may also be an array of properties * @param float $aMin the score minimum * @param float $aMax the score maximum - * @param float $aScalingFactor the score scaling factor + * @param float $aScaledValue the scaled score */ - public function __construct($aRawValue = null, $aMin = null, $aMax = null, $aScalingFactor = null) { + public function __construct($aRawValue = null, $aMin = null, $aMax = null, $aScaledValue = null) { if (!is_array($aRawValue)) { $aRawValue = [ 'raw' => $aRawValue, 'min' => $aMin, 'max' => $aMax, - 'scaled' => $aScalingFactor + 'scaled' => $aScaledValue ]; } $this->_fromArray($aRawValue); } - /** - * @param float $aValue - * @throws InvalidArgumentException - * @return null - */ - public function validate($aValue) { - if (!isset($this->min, $this->max)) { - return; - } - if ($aValue < $this->min || $aValue > $this->max) { - throw new InvalidArgumentException( - sprintf("Value must be between %s and %s", $this->min, $this->max) - ); - } - } - - /** - * @param int $aPrecision a rounding precision integer - * @return null|float - */ - public function getValue($aPrecision = self::DEFAULT_PRECISION) { - if (!isset($this->raw)) { - return null; - } - if (isset($this->scaled)) { - return round($this->raw * $this->scaled, $aPrecision); - } - return round($this->raw, $aPrecision); - } - /** * @param float $value * @throws InvalidArgumentException * @return self */ public function setScaled($value) { - if ($value < static::SCALE_MIN || $value > static::SCALE_MAX) { - throw new InvalidArgumentException(sprintf( - "Scale must be between %s and %s [%s]", - static::SCALE_MIN, - static::SCALE_MAX, - $value - )); + if ($value < static::SCALE_MIN) { + throw new InvalidArgumentException( + sprintf( "Value must be greater than or equal to %s [%s]", static::SCALE_MIN, $value) + ); + } + if ($value > static::SCALE_MAX) { + throw new InvalidArgumentException( + sprintf( "Value must be less than or equal to %s [%s]", static::SCALE_MAX, $value) + ); } $this->scaled = (float) $value; return $this; @@ -143,10 +114,21 @@ public function getScaled() { /** * @param float $value + * @throws InvalidArgumentException * @return self */ public function setRaw($value) { - $this->validate($value); + if (isset($this->min) && $value < $this->min) { + throw new InvalidArgumentException( + sprintf("Value must be greater than or equal to 'min' (%s) [%s]", $this->min, $value) + ); + } + if (isset($this->max) && $value > $this->max) { + throw new InvalidArgumentException( + sprintf("Value must be less than or equal to 'max' (%s) [%s]", $this->max, $value) + ); + } + $this->raw = (float) $value; return $this; } @@ -164,8 +146,15 @@ public function getRaw() { * @return self */ public function setMin($value) { + if (isset($this->raw) && $value > $this->raw) { + throw new InvalidArgumentException( + sprintf("Value must be less than or equal to 'raw' (%s) [%s]", $this->raw, $value) + ); + } if (isset($this->max) && $value >= $this->max) { - throw new InvalidArgumentException("Min must be less than max"); + throw new InvalidArgumentException( + sprintf("Value must be less than 'max' (%s) [%s]", $this->max, $value) + ); } $this->min = (float) $value; return $this; @@ -184,8 +173,15 @@ public function getMin() { * @return self */ public function setMax($value) { + if (isset($this->raw) && $value < $this->raw) { + throw new InvalidArgumentException( + sprintf("Value must be greater than or equal to 'raw' (%s) [%s]", $this->raw, $value) + ); + } if (isset($this->min) && $value <= $this->min) { - throw new InvalidArgumentException("Max must be greater than min"); + throw new InvalidArgumentException( + sprintf("Value must be greater than 'min' (%s) [%s]", $this->min, $value) + ); } $this->max = (float) $value; return $this; diff --git a/tests/ScoreTest.php b/tests/ScoreTest.php index 4dd98de..f66623a 100644 --- a/tests/ScoreTest.php +++ b/tests/ScoreTest.php @@ -49,128 +49,174 @@ public function testUsesAsVersionTrait() { $this->assertContains('TinCan\AsVersionTrait', class_uses('TinCan\Score')); } - public function testSetScaledThrowsException() { - $this->setExpectedException( - 'InvalidArgumentException', - sprintf('Scale must be between %s and %s [5]', Score::SCALE_MIN, Score::SCALE_MAX) - ); + public function testScaled() { $score = new Score; - $score->setScaled(5); - } + $score->setScaled(0.9); - public function testSetMinThrowsException() { - $this->setExpectedException('InvalidArgumentException', 'Min must be less than max'); - $score = new Score(['max' => 3.7]); - $score->setMin(8.1); + $this->assertEquals($score->getScaled(), 0.9); + $this->assertInternalType('float', $score->getScaled()); } - public function testSetMaxThrowsException() { - $this->setExpectedException('InvalidArgumentException', 'Max must be greater than min'); - $score = new Score(['min' => 5.3, 'max' => 3.7]); + public function testSetScaledBelowMin() { + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('Value must be greater than or equal to %s [-5]', Score::SCALE_MIN) + ); + $score = new Score; + $score->setScaled(-5); } - public function testSetRawThrowsException() { - $score = new Score(['min' => 1.5, 'max' => 4.3]); + public function testSetScaledAboveMax() { $this->setExpectedException( 'InvalidArgumentException', - 'Value must be between 1.5 and 4.3' + sprintf('Value must be less than or equal to %s [5]', Score::SCALE_MAX) ); - $score->setRaw(1); + $score = new Score; + $score->setScaled(5); } - public function testGetRawReturnsFloat() { - $score = new Score('1.5'); + public function testRaw() { + $score = new Score; + $score->setRaw(90); + + $this->assertEquals($score->getRaw(), 90); $this->assertInternalType('float', $score->getRaw()); - } - public function testGetMinReturnsFloat() { - $score = new Score(null, '1.5'); - $this->assertInternalType('float', $score->getMin()); + $score = new Score(['min' => 65, 'max' => 85]); + $score->setRaw(75); + $this->assertEquals($score->getRaw(), 75, 'between min and max'); + + $score = new Score(['min' => 65]); + $score->setRaw(65); + $this->assertEquals($score->getRaw(), 65, 'same as min'); + + $score = new Score(['max' => 65]); + $score->setRaw(65); + $this->assertEquals($score->getRaw(), 65, 'same as max'); } - public function testGetMaxReturnsFloat() { - $score = new Score(null, null, '1.5'); - $this->assertInternalType('float', $score->getMax()); + public function testSetRawBelowMin() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be greater than or equal to \'min\' (60) [50]' + ); + $score = new Score(['min' => 60]); + $score->setRaw(50); } - public function testGetScaledReturnsFloat() { - $score = new Score(null, null, null, '0.5'); - $this->assertInternalType('float', $score->getScaled()); + public function testSetRawAboveMax() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be less than or equal to \'max\' (90) [95]' + ); + $score = new Score(['max' => 90]); + $score->setRaw(95); } - public function testGetValueWithoutRawReturnsNull() { + public function testMin() { $score = new Score; - $this->assertNull($score->getValue()); + $score->setMin(9); + + $this->assertEquals($score->getMin(), 9); + $this->assertInternalType('float', $score->getMin()); + + $score = new Score(['raw' => 65, 'max' => 85]); + $score->setMin(35); + $this->assertEquals($score->getMin(), 35, 'below raw'); + + $score = new Score(['raw' => 35, 'max' => 85]); + $score->setMin(35); + $this->assertEquals($score->getMin(), 35, 'equal to raw'); } - public function testGetValueWithoutScaledReturnsRoundedRaw() { - $raw = 3.92013; - $score = new Score($raw); - $this->assertEquals( - round($raw, Score::DEFAULT_PRECISION), - $score->getValue() + public function testSetMinAboveRaw() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be less than or equal to \'raw\' (50) [60]' ); + $score = new Score(['raw' => 50]); + $score->setMin(60); } - public function testGetValueWithScaledReturnsScaledAndRoundedRaw() { - $raw = 3.92013; - $scaled = 0.8; - $score = new Score($raw, null, null, $scaled); - $this->assertEquals( - round($raw * $scaled, Score::DEFAULT_PRECISION), - $score->getValue() + public function testSetMinAboveMax() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be less than \'max\' (90) [95]' ); + $score = new Score(['max' => 90]); + $score->setMin(95); } - public function testAsVersion() { - $args = [ - 'raw' => '1.5', - 'min' => '1.0', - 'max' => '2.0', - 'scaled' => '.95' - ]; - $obj = new Score($args); - $versioned = $obj->asVersion('1.0.0'); + public function testMax() { + $score = new Score; + $score->setMax(96.3); - $this->assertEquals($versioned, $args, "version: 1.0.0"); - } + $this->assertEquals($score->getMax(), 96.3); + $this->assertInternalType('float', $score->getMax()); - public function testAsVersionEmpty() { - $obj = new Score([]); - $versioned = $obj->asVersion('1.0.0'); + $score = new Score(['raw' => 65, 'min' => 35]); + $score->setMax(85.4); + $this->assertEquals($score->getMax(), 85.4, 'above raw'); - $this->assertEquals($versioned, [], "version: 1.0.0"); + $score = new Score(['raw' => 35, 'min' => 15]); + $score->setMax(35); + $this->assertEquals($score->getMax(), 35, 'equal to raw'); } - public function testAsVersionSingleZero() { - $args = [ - 'raw' => 0 - ]; - $obj = new Score($args); - $versioned = $obj->asVersion('1.0.0'); + public function testSetMaxBelowRaw() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be greater than or equal to \'raw\' (60) [50]' + ); + $score = new Score(['raw' => 60]); + $score->setMax(50); + } - $this->assertEquals($versioned, $args, "version: 1.0.0"); + public function testSetMaxBelowMin() { + $this->setExpectedException( + 'InvalidArgumentException', + 'Value must be greater than \'min\' (10) [5]' + ); + $score = new Score(['min' => 10]); + $score->setMax(5); + } - $args = [ - 'scaled' => 0 - ]; - $obj = new Score($args); + /** + * @dataProvider asVersionDataProvider + */ + public function testAsVersion($args) { + $obj = new Score($args); $versioned = $obj->asVersion('1.0.0'); $this->assertEquals($versioned, $args, "version: 1.0.0"); } - public function testAsVersionWithZeroScores() { - $args = [ - 'raw' => '0', - 'min' => '-1.0', - 'max' => 2.0, - 'scaled' => 0 + public function asVersionDataProvider() { + return [ + 'basic' => [ + [ + 'raw' => '1.5', + 'min' => '1.0', + 'max' => '2.0', + 'scaled' => '.95' + ] + ], + 'empty' => [[]], + 'zero raw' => [ + [ 'raw' => 0 ] + ], + 'zero scaled' => [ + [ 'scaled' => 0 ] + ], + 'multiple zeros' => [ + [ + 'raw' => '0', + 'min' => '-1.0', + 'max' => 2.0, + 'scaled' => 0 + ] + ] ]; - $obj = new Score($args); - $versioned = $obj->asVersion('1.0.0'); - - $this->assertEquals($versioned, $args, "version: 1.0.0"); } public function testCompareWithSignature() { @@ -250,20 +296,10 @@ public function testCompareWithSignature() { [ 'description' => 'full: max mismatch', 'objArgs' => $full, - 'sigArgs' => array_replace($full, ['max' => 10]), + 'sigArgs' => array_replace($full, ['max' => 98]), 'reason' => 'Comparison of max failed: value is not the same' ] ]; $this->runSignatureCases("TinCan\Score", $cases); } - - public function testZeroValue() { - $args = [ - 'raw' => 0 - ]; - $obj = new Score($args); - $versioned = $obj->asVersion('1.0.0'); - - $this->assertEquals($versioned, $args, "raw with 0 as value"); - } }