From 43c247fcf4fd5d2484378aecbf2cdd020bfa853a Mon Sep 17 00:00:00 2001 From: Roland Oduberu Date: Fri, 27 Nov 2020 11:07:29 +0100 Subject: [PATCH] added validator --- src/Deck/Rank.php | 35 +++++- src/Evaluate.php | 9 +- src/Exceptions/InvalidFileContent.php | 10 ++ src/Validator.php | 167 ++++++++++++++++++++++++++ tests/Unit/EvaluateTest.php | 10 ++ tests/Unit/ValidatorTest.php | 64 ++++++++++ tests/__data/invalid.txt | 1 + 7 files changed, 290 insertions(+), 6 deletions(-) create mode 100644 src/Exceptions/InvalidFileContent.php create mode 100644 src/Validator.php create mode 100644 tests/Unit/ValidatorTest.php create mode 100644 tests/__data/invalid.txt diff --git a/src/Deck/Rank.php b/src/Deck/Rank.php index dc01ffc..87c93fa 100644 --- a/src/Deck/Rank.php +++ b/src/Deck/Rank.php @@ -5,15 +5,42 @@ class Rank { + /** + * @const string + */ + public const KING = 'K'; + public const ACE = 'A'; + public const JACK = 'J'; + public const QUEEN = 'Q'; + /** * This maps lettered ranks to numbers. * * @const array */ public const LETTERED_RANKS_TO_NUMBER = [ - 'K' => 13, - 'Q' => 12, - 'J' => 11, - 'A' => 1 + self::KING => 13, + self::QUEEN => 12, + self::JACK => 11, + self::ACE => 1 + ]; + + /** + * @const array + */ + public const LIST = [ + self::JACK, + self::QUEEN, + self::KING, + self::ACE, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2 ]; } diff --git a/src/Evaluate.php b/src/Evaluate.php index d91142b..7ee9c0e 100644 --- a/src/Evaluate.php +++ b/src/Evaluate.php @@ -8,6 +8,7 @@ use Roliod\TexasHUPoker\Rules\Contracts\Rule as RuleContract; use Roliod\TexasHUPoker\Deck\Factories\Entity as EntityFactory; use Roliod\TexasHUPoker\Exceptions\FileDoesNotExist as FileDoesNotExistException; +use Roliod\TexasHUPoker\Exceptions\InvalidFileContent as InvalidFileContentException; class Evaluate { @@ -27,7 +28,7 @@ public function __construct( /** * @return string - * @throws FileDoesNotExistException + * @throws FileDoesNotExistException|InvalidFileContentException */ public function rank(): string { @@ -37,9 +38,13 @@ public function rank(): string throw new FileDoesNotExistException($e->getMessage()); } + $validator = Validator::create($fileContent); + if ($validator->hasError()) { + throw new InvalidFileContentException($validator->error()); + } + $hands = explode(PHP_EOL, $fileContent); $convertedHands = $this->convertUnicodeSuiteCharactersToSuiteString($hands); - $reordersHands = $this->convertSuiteStringToUnicodeSuite( $this->reorderBasedOnHierarchy($convertedHands) ); diff --git a/src/Exceptions/InvalidFileContent.php b/src/Exceptions/InvalidFileContent.php new file mode 100644 index 0000000..3c245a8 --- /dev/null +++ b/src/Exceptions/InvalidFileContent.php @@ -0,0 +1,10 @@ +deck = $deck; + + $this->validate(); + } + + /** + * @return $this + */ + private function validate(): self + { + $deckToArray = explode(PHP_EOL, $this->deck); + + if ($this->validateHandCount($deckToArray) === false) { + return $this; + } + + if ($this->validateRanks($deckToArray) === false) { + return $this; + } + + if ($this->validateSuits($deckToArray) === false) { + return $this; + } + + return $this; + } + + /** + * @return bool + */ + public function hasError(): bool + { + return $this->hasError; + } + + /** + * @return bool + */ + public function isValid(): bool + { + return $this->isValid; + } + + /** + * @return string|null + */ + public function error(): ?string + { + return $this->error; + } + + /** + * @param string $deck + * + * @return $this + */ + public static function create(string $deck): self + { + return new self($deck); + } + + /** + * @param array $deck + * + * @return bool + */ + private function validateHandCount(array $deck): bool + { + foreach ($deck as $sequence) { + $hand = explode(' ', $sequence); + + if (count($hand) !== 5) { + $this->error = "Sequence count must be 5 each. Provided: $sequence"; + $this->isValid = false; + $this->hasError = true; + return false; + } + } + + return true; + } + + /** + * @param array $deck + * + * @return bool + */ + private function validateRanks(array $deck): bool + { + foreach ($deck as $hand) { + $ranks = $this->getRanksFromSequence($hand); + + foreach ($ranks as $rank) { + if (!in_array($rank,RANK::LIST)) { + $this->error = "Invalid rank provided: $rank"; + $this->isValid = false; + $this->hasError = true; + return false; + } + } + } + + return true; + } + + /** + * @param array $deck + * + * @return bool + */ + private function validateSuits(array $deck): bool + { + foreach ($deck as $hand) { + $suits = $this->getSuitsFromSequence($hand); + + foreach ($suits as $suit) { + if (!array_key_exists($suit, Suite::UNICODE_TO_STRING)) { + $this->error = "Invalid suit provided: $suit"; + $this->isValid = false; + $this->hasError = true; + return false; + } + } + } + + return true; + } +} diff --git a/tests/Unit/EvaluateTest.php b/tests/Unit/EvaluateTest.php index b7933ea..ca76538 100644 --- a/tests/Unit/EvaluateTest.php +++ b/tests/Unit/EvaluateTest.php @@ -6,6 +6,7 @@ use Tests\BaseTestCase; use Roliod\TexasHUPoker\Evaluate; use Roliod\TexasHUPoker\Exceptions\FileDoesNotExist as FileDoesNotExistException; +use Roliod\TexasHUPoker\Exceptions\InvalidFileContent as InvalidFileContentException; class EvaluateTest extends BaseTestCase { @@ -29,4 +30,13 @@ public function testItFailsWithAnInvalidDeckFilePath(): void $evaluator = new Evaluate('invalid-path.text'); $evaluator->rank(); } + + public function testItFailsWithInvalidFileContent(): void + { + $this->expectException(InvalidFileContentException::class); + $evaluator = new Evaluate( + __DIR__ . '/../__data/invalid.txt' + ); + $evaluator->rank(); + } } diff --git a/tests/Unit/ValidatorTest.php b/tests/Unit/ValidatorTest.php new file mode 100644 index 0000000..2c6c122 --- /dev/null +++ b/tests/Unit/ValidatorTest.php @@ -0,0 +1,64 @@ +isValid()); + self::assertSame($hasError, $validator->hasError()); + self::assertSame($errorMessage, $validator->error()); + } + + /** + * @return array[] + */ + public function provideDeckData(): array + { + return [ + 'invalid_hand_count' => [ + 'input' => "3H 3J 3J 4J 5J\n" . "3 3 3 3", + 'is_valid' => false, + 'has_error' => true, + 'expected_message' => 'Sequence count must be 5 each. Provided: 3 3 3 3' + ], + 'invalid_rank' => [ + 'input' => "QH JJ 10J AJ KJ\n" . "QH 18J 10J AJ KJ", + 'is_valid' => false, + 'has_error' => true, + 'expected_message' => 'Invalid rank provided: 18' + ], + 'invalid_suit' => [ + 'input' => "QH JJ 10J AJ KJ\n" . "QH QJ 10J AJ KJ", + 'is_valid' => false, + 'has_error' => true, + 'expected_message' => 'Invalid suit provided: H' + ], + 'valid' => [ + 'input' => "10❤ 10♦ 10♠ 9♣ 9♦\n" . "4♠ J♠ 8♠ 2♠ 9♠", + 'is_valid' => true, + 'has_error' => false, + 'expected_message' => null + ] + ]; + } +} diff --git a/tests/__data/invalid.txt b/tests/__data/invalid.txt new file mode 100644 index 0000000..e466dcb --- /dev/null +++ b/tests/__data/invalid.txt @@ -0,0 +1 @@ +invalid \ No newline at end of file