mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-15 20:46:26 +00:00
Add test, Disable TREND_BEST_FIT, POLYNOMIAL_BEST_FIT
This commit is contained in:
@@ -3,11 +3,14 @@
|
||||
namespace PhpOffice\PhpSpreadsheet\Shared\Trend;
|
||||
|
||||
use Matrix\Matrix;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
|
||||
|
||||
// Phpstan and Scrutinizer seem to have legitimate complaints.
|
||||
// $this->slope is specified where an array is expected in several places.
|
||||
// But it seems that it should always be float.
|
||||
// This code is probably not exercised at all in unit tests.
|
||||
// Private bool property $implemented is set to indicate
|
||||
// whether this implementation is correct.
|
||||
class PolynomialBestFit extends BestFit
|
||||
{
|
||||
/**
|
||||
@@ -21,6 +24,8 @@ class PolynomialBestFit extends BestFit
|
||||
*/
|
||||
protected int $order = 0;
|
||||
|
||||
private bool $implemented = false;
|
||||
|
||||
/**
|
||||
* Return the order of this polynomial.
|
||||
*/
|
||||
@@ -187,6 +192,10 @@ class PolynomialBestFit extends BestFit
|
||||
*/
|
||||
public function __construct(int $order, array $yValues, array $xValues = [])
|
||||
{
|
||||
if (!$this->implemented) {
|
||||
throw new SpreadsheetException('Polynomial Best Fit not yet implemented');
|
||||
}
|
||||
|
||||
parent::__construct($yValues, $xValues);
|
||||
|
||||
if (!$this->error) {
|
||||
|
||||
@@ -18,10 +18,8 @@ class Trend
|
||||
|
||||
/**
|
||||
* Names of the best-fit Trend analysis methods.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static array $trendTypes = [
|
||||
private const TREND_TYPES = [
|
||||
self::TREND_LINEAR,
|
||||
self::TREND_LOGARITHMIC,
|
||||
self::TREND_EXPONENTIAL,
|
||||
@@ -93,13 +91,12 @@ class Trend
|
||||
// Start by generating an instance of each available Trend method
|
||||
$bestFit = [];
|
||||
$bestFitValue = [];
|
||||
foreach (self::$trendTypes as $trendMethod) {
|
||||
foreach (self::TREND_TYPES as $trendMethod) {
|
||||
$className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendMethod . 'BestFit';
|
||||
//* @phpstan-ignore-next-line
|
||||
$bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
|
||||
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
|
||||
}
|
||||
if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
|
||||
if ($trendType !== self::TREND_BEST_FIT_NO_POLY) {
|
||||
foreach (self::$trendTypePolynomialOrders as $trendMethod) {
|
||||
$order = (int) substr($trendMethod, -1);
|
||||
$bestFit[$trendMethod] = new PolynomialBestFit($order, $yValues, $xValues);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Shared\Trend;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Trend\Trend;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BestFitTest extends TestCase
|
||||
{
|
||||
private const LBF_PRECISION = 1.0E-4;
|
||||
|
||||
public function testBestFit(): void
|
||||
{
|
||||
$xValues = [45, 55, 47, 75, 90, 100, 100, 95, 88, 50, 45, 58];
|
||||
$yValues = [15, 25, 17, 30, 41, 47, 50, 46, 37, 22, 20, 26];
|
||||
$maxGoodness = -1000.0;
|
||||
$maxType = '';
|
||||
|
||||
$type = Trend::TREND_LINEAR;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
$goodness = $result->getGoodnessOfFit();
|
||||
if ($maxGoodness < $goodness) {
|
||||
$maxGoodness = $goodness;
|
||||
$maxType = $type;
|
||||
}
|
||||
self::assertEqualsWithDelta(0.9628, $goodness, self::LBF_PRECISION);
|
||||
|
||||
$type = Trend::TREND_EXPONENTIAL;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
$goodness = $result->getGoodnessOfFit();
|
||||
if ($maxGoodness < $goodness) {
|
||||
$maxGoodness = $goodness;
|
||||
$maxType = $type;
|
||||
}
|
||||
self::assertEqualsWithDelta(0.9952, $goodness, self::LBF_PRECISION);
|
||||
|
||||
$type = Trend::TREND_LOGARITHMIC;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
$goodness = $result->getGoodnessOfFit();
|
||||
if ($maxGoodness < $goodness) {
|
||||
$maxGoodness = $goodness;
|
||||
$maxType = $type;
|
||||
}
|
||||
self::assertEqualsWithDelta(-0.0724, $goodness, self::LBF_PRECISION);
|
||||
|
||||
$type = Trend::TREND_POWER;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
$goodness = $result->getGoodnessOfFit();
|
||||
if ($maxGoodness < $goodness) {
|
||||
$maxGoodness = $goodness;
|
||||
$maxType = $type;
|
||||
}
|
||||
self::assertEqualsWithDelta(0.9946, $goodness, self::LBF_PRECISION);
|
||||
|
||||
$type = Trend::TREND_BEST_FIT_NO_POLY;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
$goodness = $result->getGoodnessOfFit();
|
||||
self::assertSame($maxGoodness, $goodness);
|
||||
self::assertSame(lcfirst($maxType), $result->getBestFitType());
|
||||
|
||||
try {
|
||||
$type = Trend::TREND_BEST_FIT;
|
||||
$result = Trend::calculate($type, $yValues, $xValues);
|
||||
self::fail('should have failed - TREND_BEST_FIT includes polynomials which are not implemented yet');
|
||||
} catch (SpreadsheetException $e) {
|
||||
self::assertStringContainsString('not yet implemented', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user