/**
  * @param RangedWeaponCode $rangedWeaponCode
  * @param Strength $currentStrength
  * @return int
  * @throws CanNotUseWeaponBecauseOfMissingStrength
  * @throws UnknownArmament
  * @throws UnknownBow
  */
 private function getEncounterRangeMalusByStrength(RangedWeaponCode $rangedWeaponCode, Strength $currentStrength)
 {
     if (!$rangedWeaponCode->isBow() && !$rangedWeaponCode->isThrowingWeapon()) {
         return 0;
     }
     $missingStrength = $this->getMissingStrengthForArmament($rangedWeaponCode, $currentStrength, Size::getIt(0));
     /** @noinspection ExceptionsAnnotatingAndHandlingInspection */
     return $this->tables->getRangedWeaponStrengthSanctionsTable()->getEncounterRangeSanction($missingStrength);
 }
 /**
  * @test
  * @dataProvider getCombination
  *
  * @param Race $race
  * @param GenderCode $genderCode
  * @param ExceptionalityProperties $exceptionalityProperties
  * @param ProfessionLevels $professionLevels
  * @param Tables $tables
  * @param WeightInKg $weightInKgAdjustment
  * @param HeightInCm $heightInCmAdjustment
  * @param Age $age
  * @param int $expectedStrength
  * @param int $expectedAgility
  * @param int $expectedKnack
  * @param int $expectedWill
  * @param int $expectedIntelligence
  * @param int $expectedCharisma
  */
 public function I_can_create_properties_for_any_combination(Race $race, GenderCode $genderCode, ExceptionalityProperties $exceptionalityProperties, ProfessionLevels $professionLevels, Tables $tables, WeightInKg $weightInKgAdjustment, HeightInCm $heightInCmAdjustment, Age $age, $expectedStrength, $expectedAgility, $expectedKnack, $expectedWill, $expectedIntelligence, $expectedCharisma)
 {
     $properties = new PropertiesByLevels($race, $genderCode, $exceptionalityProperties, $professionLevels, $weightInKgAdjustment, $heightInCmAdjustment, $age, $tables);
     self::assertInstanceOf(FirstLevelProperties::class, $properties->getFirstLevelProperties());
     self::assertInstanceOf(NextLevelsProperties::class, $properties->getNextLevelsProperties());
     self::assertSame($expectedStrength, $properties->getStrength()->getValue(), "{$race} {$genderCode}");
     self::assertSame($expectedAgility, $properties->getAgility()->getValue(), "{$race} {$genderCode}");
     self::assertSame($expectedKnack, $properties->getKnack()->getValue(), "{$race} {$genderCode}");
     self::assertSame($expectedWill, $properties->getWill()->getValue(), "{$race} {$genderCode}");
     self::assertSame($expectedIntelligence, $properties->getIntelligence()->getValue(), "{$race} {$genderCode}");
     self::assertSame($expectedCharisma, $properties->getCharisma()->getValue(), "{$race} {$genderCode}");
     self::assertSame($weightInKgAdjustment, $properties->getWeightInKgAdjustment());
     self::assertGreaterThan($weightInKgAdjustment->getValue(), $properties->getWeightInKg()->getValue(), "{$race} {$genderCode}");
     self::assertSame($heightInCmAdjustment, $properties->getHeightInCmAdjustment());
     self::assertGreaterThan($heightInCmAdjustment->getValue(), $properties->getHeightInCm()->getValue(), "{$race} {$genderCode}");
     self::assertEquals($expectedHeight = new Height($properties->getHeightInCm(), $tables->getDistanceTable()), $properties->getHeight());
     self::assertSame($age, $properties->getAge());
     $expectedToughness = new Toughness(Strength::getIt($expectedStrength), $race->getRaceCode(), $race->getSubraceCode(), $tables->getRacesTable());
     self::assertInstanceOf(Toughness::class, $properties->getToughness());
     self::assertSame($expectedToughness->getValue(), $properties->getToughness()->getValue(), "{$race} {$genderCode}");
     $expectedEndurance = new Endurance(Strength::getIt($expectedStrength), Will::getIt($expectedWill));
     self::assertInstanceOf(Endurance::class, $properties->getEndurance());
     self::assertSame($expectedEndurance->getValue(), $properties->getEndurance()->getValue(), "{$race} {$genderCode}");
     $expectedSize = Size::getIt($race->getSize($genderCode, $tables) + 1);
     /* size bonus by strength */
     self::assertInstanceOf(Size::class, $properties->getSize(), "{$race} {$genderCode}");
     self::assertSame($expectedSize->getValue(), $properties->getSize()->getValue(), "{$race} {$genderCode}");
     $expectedSpeed = new Speed(Strength::getIt($expectedStrength), Agility::getIt($expectedAgility), $expectedHeight);
     self::assertInstanceOf(Speed::class, $properties->getSpeed(), "{$race} {$genderCode}");
     self::assertSame($expectedSpeed->getValue(), $properties->getSpeed()->getValue(), "{$race} {$genderCode}");
     $expectedSenses = new Senses(Knack::getIt($expectedKnack), RaceCode::getIt($race->getRaceCode()), SubRaceCode::getIt($race->getSubraceCode()), $tables->getRacesTable());
     self::assertInstanceOf(Senses::class, $properties->getSenses());
     self::assertSame($expectedSenses->getValue(), $properties->getSenses()->getValue(), "{$race} {$genderCode}");
     $expectedBeauty = new Beauty(Agility::getIt($expectedAgility), Knack::getIt($expectedKnack), Charisma::getIt($expectedCharisma));
     self::assertInstanceOf(Beauty::class, $properties->getBeauty());
     self::assertSame($expectedBeauty->getValue(), $properties->getBeauty()->getValue(), "{$race} {$genderCode}");
     $expectedDangerousness = new Dangerousness(Strength::getIt($expectedStrength), Will::getIt($expectedWill), Charisma::getIt($expectedCharisma));
     self::assertInstanceOf(Dangerousness::class, $properties->getDangerousness());
     self::assertSame($expectedDangerousness->getValue(), $properties->getDangerousness()->getValue(), "{$race} {$genderCode}");
     $expectedDignity = new Dignity(Intelligence::getIt($expectedIntelligence), Will::getIt($expectedWill), Charisma::getIt($expectedCharisma));
     self::assertInstanceOf(Dignity::class, $properties->getDignity());
     self::assertSame($expectedDignity->getValue(), $properties->getDignity()->getValue(), "{$race} {$genderCode}");
     $expectedFightValue = $expectedAgility + (SumAndRound::ceil($expectedHeight->getValue() / 3) - 2);
     self::assertInstanceOf(FightNumber::class, $properties->getFightNumber());
     self::assertSame($expectedFightValue, $properties->getFightNumber()->getValue(), "{$race} {$genderCode} with height {$expectedHeight}");
     $expectedAttack = new Attack(Agility::getIt($expectedAgility));
     self::assertInstanceOf(Attack::class, $properties->getAttack());
     self::assertSame($expectedAttack->getValue(), $properties->getAttack()->getValue(), "{$race} {$genderCode}");
     $expectedShooting = new Shooting(Knack::getIt($expectedKnack));
     self::assertInstanceOf(Shooting::class, $properties->getShooting());
     self::assertSame($expectedShooting->getValue(), $properties->getShooting()->getValue(), "{$race} {$genderCode}");
     $expectedDefense = new DefenseNumber(Agility::getIt($expectedAgility));
     self::assertInstanceOf(DefenseNumber::class, $properties->getDefenseNumber());
     self::assertSame($expectedDefense->getValue(), $properties->getDefenseNumber()->getValue(), "{$race} {$genderCode}");
     $expectedDefenseAgainstShooting = new DefenseNumberAgainstShooting($expectedDefense, $expectedSize);
     self::assertInstanceOf(DefenseNumberAgainstShooting::class, $properties->getDefenseAgainstShooting());
     self::assertSame($expectedDefenseAgainstShooting->getValue(), $properties->getDefenseAgainstShooting()->getValue(), "{$race} {$genderCode}");
     $expectedWoundBoundary = new WoundBoundary($expectedToughness, $tables->getWoundsTable());
     self::assertInstanceOf(WoundBoundary::class, $properties->getWoundBoundary());
     self::assertSame($expectedWoundBoundary->getValue(), $properties->getWoundBoundary()->getValue());
     $expectedFatigueBoundary = new FatigueBoundary($expectedEndurance, $tables->getFatigueTable());
     self::assertInstanceOf(FatigueBoundary::class, $properties->getFatigueBoundary());
     self::assertSame($expectedFatigueBoundary->getValue(), $properties->getFatigueBoundary()->getValue());
 }
 /**
  * @param Race $race
  * @param GenderCode $genderCode
  * @param Tables $tables
  * @param ExceptionalityProperties $exceptionalityProperties
  * @param ProfessionLevels $professionLevels
  * @return Size
  * @throws Exceptions\TooLowStrengthAdjustment
  */
 private function createFirstLevelSize(Race $race, GenderCode $genderCode, Tables $tables, ExceptionalityProperties $exceptionalityProperties, ProfessionLevels $professionLevels)
 {
     // the race bonus is NOT count for adjustment, doesn't count to size change respectively
     $sizeModifierByStrength = $this->getSizeModifierByStrength($exceptionalityProperties->getStrength()->getValue() + $professionLevels->getFirstLevelStrengthModifier());
     $raceSize = $race->getSize($genderCode, $tables);
     return Size::getIt($raceSize + $sizeModifierByStrength);
 }
 /**
  * @test
  * @dataProvider provideBodySizeAndStrength
  * @param int $requiredStrength
  * @param int $bodySize
  * @param int $strength
  * @param mixed $expectedMissingStrength
  */
 public function I_can_get_missing_strength_and_sanction_values_for_body_armor_and_helm($requiredStrength, $bodySize, $strength, $expectedMissingStrength)
 {
     $armourer = new Armourer($tables = $this->createTables());
     $bodyArmorCode = $this->createBodyArmorCode('foo');
     $tables->shouldReceive('getArmamentsTableByArmamentCode')->with($bodyArmorCode)->andReturn($armamentsTable = $this->mockery(AbstractArmamentsTable::class));
     $armamentsTable->shouldReceive('getRequiredStrengthOf')->with($bodyArmorCode)->andReturn($requiredStrength);
     self::assertSame($expectedMissingStrength, $armourer->getMissingStrengthForArmament($bodyArmorCode, Strength::getIt($strength), Size::getIt($bodySize)));
     $helmCode = $this->createHelmCode('bar');
     $tables->shouldReceive('getArmamentsTableByArmamentCode')->with($helmCode)->andReturn($armamentsTable = $this->mockery(AbstractArmamentsTable::class));
     $armamentsTable->shouldReceive('getRequiredStrengthOf')->with($helmCode)->andReturn($requiredStrength);
     self::assertSame($expectedMissingStrength, $armourer->getMissingStrengthForArmament($helmCode, Strength::getIt($strength), Size::getIt($bodySize)));
     $tables->shouldReceive('getArmorStrengthSanctionsTable')->andReturn($armorSanctionsTable = $this->createArmorSanctionsTable());
     $armorSanctionsTable->shouldReceive('getSanctionDescription')->with($expectedMissingStrength)->andReturn('qux');
     self::assertSame('qux', $armourer->getSanctionDescriptionByStrengthWithArmor($helmCode, Strength::getIt($strength), Size::getIt($bodySize)));
     $armorSanctionsTable->shouldReceive('getAgilityMalus')->with($expectedMissingStrength)->andReturn('qux');
     self::assertSame('qux', $armourer->getAgilityMalusByStrengthWithArmor($bodyArmorCode, Strength::getIt($strength), Size::getIt($bodySize)));
 }