Skip to content

Refined precision detection #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 22 additions & 55 deletions src/Parsers/GlobeCoordinateParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author H. Snater < mediawiki@snater.com >
* @author Thiemo Mättig
*/
class GlobeCoordinateParser extends StringValueParser {

Expand Down Expand Up @@ -67,7 +68,7 @@ protected function stringParse( $value ) {
);
}

protected function detectPrecision( LatLongValue $latLong, $precisionDetector ) {
private function detectPrecision( LatLongValue $latLong, $precisionDetector ) {
if ( $this->options->hasOption( 'precision' ) ) {
return $this->options->getOption( 'precision' );
}
Expand All @@ -81,7 +82,7 @@ protected function detectPrecision( LatLongValue $latLong, $precisionDetector )
/**
* @return StringValueParser[]
*/
protected function getParsers() {
private function getParsers() {
$parsers = array();

$parsers['detectFloatPrecision'] = new FloatCoordinateParser( $this->options );
Expand All @@ -92,74 +93,40 @@ protected function getParsers() {
return $parsers;
}

protected function detectDdPrecision( $number ) {
// TODO: Implement localized decimal separator.
$split = explode( '.', $number );

$precision = 1;

if( isset( $split[1] ) ) {
$precision = pow( 10, -1 * strlen( $split[1] ) );
}

return $precision;
protected function detectDdPrecision( $degree ) {
return $this->detectFloatPrecision( $degree );
}

protected function detectDmPrecision( $number ) {
$minutes = $number * 60;

// Since arcminutes shall be used to detect the precision, precision needs at least to be an
// arcminute:
$precision = 1 / 60;

// The minute may be a float; In order to detect a proper precision, we convert the minutes
// to seconds.
if( $minutes - floor( $minutes ) > 0 ) {
$seconds = $minutes * 60;

$precision = 1 / 3600;
protected function detectDmPrecision( $degree ) {
$minutes = $degree * 60;
$split = explode( '.', round( $minutes, 6 ) );

// TODO: Implement localized decimal separator.
$secondsSplit = explode( '.', $seconds );

if( isset( $secondsSplit[1] ) ) {
$precision *= pow( 10, -1 * strlen( $secondsSplit[1] ) );
}
if ( isset( $split[1] ) ) {
return $this->detectDmsPrecision( $degree );
}

return $precision;
return 1 / 60;
}

protected function detectDmsPrecision( $number ) {
$seconds = $number * 3600;

// Since arcseconds shall be used to detect the precision, precision needs at least to be an
// arcsecond:
$precision = 1 / 3600;
protected function detectDmsPrecision( $degree ) {
$seconds = $degree * 3600;
$split = explode( '.', round( $seconds, 4 ) );

if( $number - floor( $number ) > 0 ) {
// TODO: Implement localized decimal separator.
$secondsSplit = explode( '.', $seconds );

if( isset( $secondsSplit[1] ) ) {
$precision *= pow( 10, -1 * strlen( $secondsSplit[1] ) );
}
if ( isset( $split[1] ) ) {
return pow( 10, -strlen( $split[1] ) ) / 3600;
}

return $precision;
return 1 / 3600;
}

protected function detectFloatPrecision( $number ) {
// TODO: Implement localized decimal separator.
$split = explode( '.', $number );

$precision = 1;
protected function detectFloatPrecision( $degree ) {
$split = explode( '.', round( $degree, 8 ) );

if( isset( $split[1] ) ) {
$precision = pow( 10, -1 * strlen( $split[1] ) );
if ( isset( $split[1] ) ) {
return pow( 10, -strlen( $split[1] ) );
}

return $precision;
return 1;
}

}
76 changes: 76 additions & 0 deletions tests/unit/Parsers/GlobeCoordinateParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\DataValues\Geo\Parsers;

use DataValues\Geo\Parsers\GlobeCoordinateParser;
use DataValues\Geo\Values\GlobeCoordinateValue;
use DataValues\Geo\Values\LatLongValue;
use ValueParsers\ParserOptions;
Expand All @@ -16,6 +17,7 @@
*
* @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author Thiemo Mättig
*/
class GlobeCoordinateParserTest extends StringValueParserTest {

Expand Down Expand Up @@ -175,6 +177,80 @@ public function withGlobeOptionProvider() {
return $data;
}

/**
* @dataProvider precisionDetectionProvider
* @param string $value
* @param float|int $expected
*/
public function testPrecisionDetection( $value, $expected ) {
$parser = new GlobeCoordinateParser();
/** @var GlobeCoordinateValue $globeCoordinateValue */
$globeCoordinateValue = $parser->parse( $value );

$this->assertSame( $expected, $globeCoordinateValue->getPrecision() );
}

public function precisionDetectionProvider() {
return array(
// Float
array( '10 20', 1 ),
array( '1 2', 1 ),
array( '1.3 2.4', 0.1 ),
array( '1.3 20', 0.1 ),
array( '10 2.4', 0.1 ),
array( '1.35 2.46', 0.01 ),
array( '1.357 2.468', 0.001 ),
array( '1.3579 2.468', 0.0001 ),
array( '1.00001 2.00001', 0.00001 ),
array( '1.000001 2.000001', 0.000001 ),
array( '1.0000001 2.0000001', 0.0000001 ),
array( '1.00000001 2.00000001', 0.00000001 ),
array( '1.000000001 2.000000001', 1 ),
array( '1.555555555 2.555555555', 0.00000001 ),

// Dd
array( '10° 20°', 1 ),
array( '1° 2°', 1 ),
array( '1.3° 2.4°', 0.1 ),
array( '1.3° 20°', 0.1 ),
array( '10° 2.4°', 0.1 ),
array( '1.35° 2.46°', 0.01 ),
array( '1.357° 2.468°', 0.001 ),
array( '1.3579° 2.468°', 0.0001 ),
array( '1.00001° 2.00001°', 0.00001 ),
array( '1.000001° 2.000001°', 0.000001 ),
array( '1.0000001° 2.0000001°', 0.0000001 ),
array( '1.00000001° 2.00000001°', 0.00000001 ),
array( '1.000000001° 2.000000001°', 1 ),
array( '1.555555555° 2.555555555°', 0.00000001 ),

// Dm
array( '1°3\' 2°4\'', 1 / 60 ),
array( '1°3\' 2°0\'', 1 / 60 ),
array( '1°0\' 2°4\'', 1 / 60 ),
array( '1°3.5\' 2°4.6\'', 1 / 3600 ),
array( '1°3.57\' 2°4.68\'', 1 / 36000 ),
array( '1°3.579\' 2°4.68\'', 1 / 360000 ),
array( '1°3.0001\' 2°4.0001\'', 1 / 3600000 ),
array( '1°3.00001\' 2°4.00001\'', 1 / 36000000 ),
array( '1°3.000001\' 2°4.000001\'', 1 / 36000000 ),
array( '1°3.0000001\' 2°4.0000001\'', 1 / 60 ),
array( '1°3.5555555\' 2°4.5555555\'', 1 / 36000000 ),

// Dms
array( '1°3\'5" 2°4\'6"', 1 / 3600 ),
array( '1°3\'5" 2°0\'0"', 1 / 3600 ),
array( '1°0\'0" 2°4\'6"', 1 / 3600 ),
array( '1°3\'0" 2°4\'0"', 1 / 3600 ),
array( '1°3\'5.7" 2°4\'6.8"', 1 / 36000 ),
array( '1°3\'5.79" 2°4\'6.8"', 1 / 360000 ),
array( '1°3\'5.001" 2°4\'6.001"', 1 / 3600000 ),
array( '1°3\'5.0001" 2°4\'6.0001"', 1 / 36000000 ),
array( '1°3\'5.00001" 2°4\'6.00001"', 1 / 3600 ),
array( '1°3\'5.55555" 2°4\'6.55555"', 1 / 36000000 ),
);
}

/**
* @see ValueParserTestBase::getParserClass
*
Expand Down