87 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace Scientific;
 | 
						|
 | 
						|
use InvalidArgumentException;
 | 
						|
 | 
						|
abstract class Quantity
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * https://en.wikipedia.org/wiki/Metric_prefix
 | 
						|
     */
 | 
						|
    private const METRIC_PREFIXES = [
 | 
						|
        'yotta' => 'Y',
 | 
						|
        'zetta' => 'Z',
 | 
						|
        'exa'   => 'E',
 | 
						|
        'peta'  => 'P',
 | 
						|
        'tera'  => 'T',
 | 
						|
        'giga'  => 'G',
 | 
						|
        'mega'  => 'M',
 | 
						|
        'kilo'  => 'k',
 | 
						|
        'hecto' => 'h',
 | 
						|
        'deca'  => 'da',
 | 
						|
        'unit'  => '',
 | 
						|
        'deci'  => 'd',
 | 
						|
        'centi' => 'c',
 | 
						|
        'milli' => 'm',
 | 
						|
        'micro' => 'μ',
 | 
						|
        'nano'  => 'n',
 | 
						|
        'pico'  => 'p',
 | 
						|
        'femto' => 'f',
 | 
						|
        'atto'  => 'a',
 | 
						|
        'zepto' => 'z',
 | 
						|
        'yocto' => 'y',
 | 
						|
    ];
 | 
						|
 | 
						|
    abstract protected function getSymbol(): string;
 | 
						|
 | 
						|
    abstract protected function getName(): string;
 | 
						|
 | 
						|
    public function __construct(
 | 
						|
        private Unit $value
 | 
						|
    )
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    final public static function fromValue(float $value): static
 | 
						|
    {
 | 
						|
        return new static(new Unit($value));
 | 
						|
    }
 | 
						|
 | 
						|
    final public function getValue(): Unit
 | 
						|
    {
 | 
						|
        return $this->value;
 | 
						|
    }
 | 
						|
 | 
						|
    final public function format(string $prefix = 'auto'): string
 | 
						|
    {
 | 
						|
        if ($prefix === 'auto') {
 | 
						|
            $prefix = $this->getAppropriatePrefix();
 | 
						|
        } else if (!method_exists($this->value, $prefix)) {
 | 
						|
            throw new InvalidArgumentException('Invalid size: ' . $prefix);
 | 
						|
        }
 | 
						|
 | 
						|
        $value = $this->value->{$prefix}();
 | 
						|
        $prefix = self::METRIC_PREFIXES[$prefix] ?? '?';
 | 
						|
        $symbol = $this->getSymbol();
 | 
						|
 | 
						|
        return sprintf('%.3g %s%s', $value, $prefix, $symbol);
 | 
						|
    }
 | 
						|
 | 
						|
    private function getAppropriatePrefix(): string
 | 
						|
    {
 | 
						|
        foreach (array_keys(self::METRIC_PREFIXES) as $prefix) {
 | 
						|
            $value = $this->value->{$prefix}();
 | 
						|
            if ($value >= 1. && $value < 1000.) {
 | 
						|
                return $prefix;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return 'unit';
 | 
						|
    }
 | 
						|
 | 
						|
    public function __toString(): string
 | 
						|
    {
 | 
						|
        return $this->format();
 | 
						|
    }
 | 
						|
}
 |