Skip to content

Commit

Permalink
added validator
Browse files Browse the repository at this point in the history
  • Loading branch information
roliod committed Nov 27, 2020
1 parent ad996c1 commit 43c247f
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 6 deletions.
35 changes: 31 additions & 4 deletions src/Deck/Rank.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
];
}
9 changes: 7 additions & 2 deletions src/Evaluate.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -27,7 +28,7 @@ public function __construct(

/**
* @return string
* @throws FileDoesNotExistException
* @throws FileDoesNotExistException|InvalidFileContentException
*/
public function rank(): string
{
Expand All @@ -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)
);
Expand Down
10 changes: 10 additions & 0 deletions src/Exceptions/InvalidFileContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Roliod\TexasHUPoker\Exceptions;

use Exception;

class InvalidFileContent extends Exception
{
}
167 changes: 167 additions & 0 deletions src/Validator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php
declare(strict_types=1);

namespace Roliod\TexasHUPoker;

use Roliod\TexasHUPoker\Deck\Rank;
use Roliod\TexasHUPoker\Deck\Suite;
use Roliod\TexasHUPoker\Rules\Concerns\CanGetRanksFromSequence;
use Roliod\TexasHUPoker\Rules\Concerns\CanGetSuitsFromSequence;

class Validator
{
use CanGetSuitsFromSequence, CanGetRanksFromSequence;

/**
* @var string
*/
private $deck;

/**
* @var bool
*/
private $hasError = false;

/**
* @var string|null
*/
private $error;

/**
* @var bool
*/
private $isValid = true;

/**
* @param string $deck
*/
private function __construct(string $deck)
{
$this->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;
}
}
10 changes: 10 additions & 0 deletions tests/Unit/EvaluateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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();
}
}
64 changes: 64 additions & 0 deletions tests/Unit/ValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);

namespace Tests\Unit;

use Tests\BaseTestCase;
use Roliod\TexasHUPoker\Validator;

class ValidatorTest extends BaseTestCase
{
/**
* @dataProvider provideDeckData
*
* @param string $input
* @param bool $isValid
* @param bool $hasError
* @param string|null $errorMessage
*/
public function testItCanValidateInput(
string $input,
bool $isValid,
bool $hasError,
?string $errorMessage = null
): void {
$validator = Validator::create($input);

self::assertSame($isValid, $validator->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
]
];
}
}
1 change: 1 addition & 0 deletions tests/__data/invalid.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid

0 comments on commit 43c247f

Please sign in to comment.