AbstractUnit.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. namespace App\Yr\Forecast\Tabular\Time;
  3. /**
  4. * Time-object entity should inherit this
  5. */
  6. abstract class AbstractUnit implements DiffInterface {
  7. const DEFAULT_VARIANCE = 2;
  8. private $value = 0;
  9. private $unit;
  10. /**
  11. * @param float The value
  12. * @param float The unit
  13. */
  14. public function __construct(float $value, string $unit) {
  15. $this->value = $value;
  16. $this->unit = $unit;
  17. }
  18. /**
  19. * Determines if the classes can operate on each other
  20. *
  21. * @param AbstractUnit $with Class to operate on
  22. * @param bool $throw Set to true if function should throw exception
  23. *
  24. * @return bool True if they can
  25. * @throws \InvalidArgumentException if $throw set to true
  26. */
  27. private function canOperate(AbstractUnit $with, bool $throw = false): bool {
  28. if ($with instanceof $this || $with instanceof CustomUnit)
  29. return true;
  30. if ($this instanceof CustomUnit && $with instanceof AbstractUnit)
  31. return true;
  32. if ($throw)
  33. throw new \InvalidArgumentException(sprintf(
  34. "Invalid type <%s>, expected of type \"%s\" or \"%s\"",
  35. get_class($with), get_class($this), CustomUnit::class
  36. ));
  37. return false;
  38. }
  39. /**
  40. * Transform custom unit to self
  41. */
  42. protected function transformClass(CustomUnit $cu): self {
  43. return unserialize(preg_replace(
  44. '/^O:\d+:"[^"]++"/',
  45. sprintf('O:%d:"%s"', strlen(static::class), static::class),
  46. serialize($cu)
  47. ));
  48. }
  49. /**
  50. * Addition method
  51. *
  52. * @param AbstractUnit $with Unit to add with
  53. * @thows \InvalidArgumentException
  54. * */
  55. public function add(AbstractUnit $with): self {
  56. $this->canOperate($with, true);
  57. return $this->transformClass(
  58. new CustomUnit($this->getValue() + $with->getValue(), $with->getUnit())
  59. );
  60. }
  61. /**
  62. * Subtraction method
  63. *
  64. * @param AbstractUnit $with Unit to sub with
  65. * @thows \InvalidArgumentException
  66. * */
  67. public function sub(AbstractUnit $with): self {
  68. $this->canOperate($with, true);
  69. return $this->transformClass(
  70. new CustomUnit($this->getValue() - $with->getValue(), $with->getUnit())
  71. );
  72. }
  73. /**
  74. * Multiplication method
  75. *
  76. * @param AbstractUnit $with Unit to multiply with
  77. * @thows \InvalidArgumentException
  78. * */
  79. public function mul(AbstractUnit $with): self {
  80. $this->canOperate($with, true);
  81. return $this->transformClass(
  82. new CustomUnit($this->getValue() * $with->getValue(), $with->getUnit())
  83. );
  84. }
  85. /**
  86. * Divide method
  87. *
  88. * @param AbstractUnit $with Unit to divide with
  89. * @thows \InvalidArgumentException
  90. * */
  91. public function div(AbstractUnit $with): self {
  92. $this->canOperate($with, true);
  93. return $this->transformClass(
  94. new CustomUnit($this->getValue() / $with->getValue(), $with->getUnit())
  95. );
  96. }
  97. /**
  98. * Get the value
  99. *
  100. * @return float
  101. */
  102. public function getValue(): float {
  103. return $this->value;
  104. }
  105. /**
  106. * Return the unit (e.g «degree»)
  107. *
  108. * @return string
  109. */
  110. public function getUnit(): string {
  111. return $this->unit;
  112. }
  113. /**
  114. * Note! Working on floats, so operates on 100-times values,
  115. * so result should be divided with 100 to get the actual
  116. * difference.
  117. *
  118. * {@inheritDoc}
  119. */
  120. public function diff(DiffInterface $d): int {
  121. if ($this->canOperate($d, false))
  122. return (int)($this->sub($d)->getValue() * 100);
  123. return 0;
  124. }
  125. public function __toString(): string {
  126. return sprintf(
  127. "%s: %01.1f %s", basename(str_replace(
  128. '\\', DIRECTORY_SEPARATOR, get_class($this)
  129. )), $this->value, $this->unit);
  130. }
  131. }