/** * @param $value * @param $fromUnit * @param $toUnit * @return float * @throws UnknownUnit * @throws \Granam\Float\Tools\Exceptions\WrongParameterType * @throws \Granam\Float\Tools\Exceptions\ValueLostOnCast */ private function getValueInDifferentUnit($value, $fromUnit, $toUnit) { if ($fromUnit === $toUnit) { return ToFloat::toFloat($value); } if ($fromUnit === self::M && $toUnit === self::KM) { return $value / 1000; } if ($fromUnit === self::KM && $toUnit === self::M) { return $value * 1000; } throw new UnknownUnit('Unknown one or both from ' . ValueDescriber::describe($fromUnit) . ' to ' . ValueDescriber::describe($toUnit) . ' unit(s)'); }
/** * @param Distance $distance * @return int */ public function getAttackNumberModifierByDistance(Distance $distance) { $distanceInMeters = $distance->getMeters(); $orderedByDistanceDesc = $this->getOrderedByDistanceAsc(); $attackNumberModifierCandidate = null; foreach ($orderedByDistanceDesc as $distanceInMetersFrom => $row) { /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ if ($distanceInMeters >= ToFloat::toPositiveFloat($distanceInMetersFrom)) { $attackNumberModifierCandidate = $row[self::RANGED_ATTACK_NUMBER_MODIFIER]; } } return $attackNumberModifierCandidate; }
/** * @param Distance $distance * @return int * @throws Exceptions\DistanceOutOfKnownValues */ public function getAttackNumberModifierByDistance(Distance $distance) { $distanceInMeters = $distance->getMeters(); $orderedByDistanceDesc = $this->getOrderedByDistanceAsc(); foreach ($orderedByDistanceDesc as $distanceInMetersTo => $row) { /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ if ($distanceInMeters <= ToFloat::toPositiveFloat($distanceInMetersTo)) { // including return $row[self::RANGED_ATTACK_NUMBER_MODIFIER]; } } throw new Exceptions\DistanceOutOfKnownValues("Given distance {$distance} is so far so we do not have values for it"); }
/** * Values may be already ordered from file, but have to be sure. * * @return array|\string[][] */ protected function getOrderedByDistanceAsc() { $values = $this->getIndexedValues(); uksort($values, function ($oneDistanceInMeters, $anotherDistanceInMeters) { /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ $oneDistanceInMeters = ToFloat::toPositiveFloat($oneDistanceInMeters); $anotherDistanceInMeters = ToFloat::toPositiveFloat($anotherDistanceInMeters); if ($oneDistanceInMeters < $anotherDistanceInMeters) { return -1; // lowest first } if ($oneDistanceInMeters > $anotherDistanceInMeters) { return 1; } return 0; }); return $values; }
/** * @param number $number * * @return int */ public static function ceiledThird($number) { return self::ceil(ToFloat::toFloat($number) / 3); }
/** * @param mixed $value * @param bool $strict = true allows only explicit values, not null and empty string * @param bool $paranoid Throws exception if some value is lost on cast because of rounding * @throws \Granam\Float\Tools\Exceptions\PositiveFloatCanNotBeNegative * @throws \Granam\Float\Tools\Exceptions\WrongParameterType * @throws \Granam\Float\Tools\Exceptions\ValueLostOnCast */ public function __construct($value, $strict = true, $paranoid = false) { /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ parent::__construct(ToFloat::toPositiveFloat($value, $strict, $paranoid)); }
private function normalizeValueForType($value, $type) { $value = trim($value); switch ($type) { case self::BOOLEAN: return ToBoolean::toBoolean($value, false); case self::INTEGER: return $value === '' ? false : ToInteger::toInteger($this->normalizeMinus($value)); case self::POSITIVE_INTEGER: return $value === '' ? false : ToInteger::toPositiveInteger($this->normalizeMinus($value)); case self::NEGATIVE_INTEGER: return $value === '' ? false : ToInteger::toNegativeInteger($this->normalizeMinus($value)); case self::FLOAT: return $value === '' ? false : ToFloat::toFloat($this->normalizeMinus($value)); default: // string return $value; } }
/** * @param mixed $value * @param bool $strict = true allows only explicit values, not null and empty string * @param bool $paranoid Throws exception if some value is lost on cast because of rounding * @throws \Granam\Float\Tools\Exceptions\WrongParameterType * @throws \Granam\Float\Tools\Exceptions\ValueLostOnCast */ public function __construct($value, $strict = true, $paranoid = false) { parent::__construct(ToFloat::toFloat($value, $strict, $paranoid)); }
/** * @param mixed $value * @return number * @throws \Granam\Float\Tools\Exceptions\WrongParameterType * @throws \Granam\Float\Tools\Exceptions\ValueLostOnCast */ protected function normalizeValue($value) { return ToFloat::toFloat($value); }
/** * @param float $searchedValue * @param array $closestLower * @param array $closestHigher * * @return int */ private function getBonusClosestTo($searchedValue, array $closestLower, array $closestHigher) { $searchedValue = ToFloat::toFloat($searchedValue); $closerValue = $this->getCloserValue($searchedValue, key($closestLower), key($closestHigher)); if ($closerValue !== false) { if (array_key_exists("{$closerValue}", $closestLower)) { $bonuses = $closestLower["{$closerValue}"]; } else { $bonuses = $closestHigher["{$closerValue}"]; } // matched single table-value, maybe with more bonuses, the lowest bonus should be taken return min($bonuses); // PPH page 11, right column } else { // both table border-values are equally close to the value, we will choose from bonuses of both borders $bonuses = array_merge(count($closestLower) > 0 ? current($closestLower) : [], count($closestHigher) > 0 ? current($closestHigher) : []); // matched two table-values, more bonuses for sure, the highest bonus should be taken return max($bonuses); // PPH page 11, right column } }