Last active
December 30, 2023 08:10
-
-
Save laracasts/6ddc75cdf6e2749da6a1eccc554e9dc3 to your computer and use it in GitHub Desktop.
Tennis Match Laracasts Kata - https://laracasts.com/series/code-katas-with-phpunit/episodes/6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
class Player | |
{ | |
/** | |
* @var string | |
*/ | |
public string $name; | |
/** | |
* @var int | |
*/ | |
public int $points = 0; | |
/** | |
* Create a new player. | |
* | |
* @param string $name | |
*/ | |
public function __construct(string $name) | |
{ | |
$this->name = $name; | |
} | |
/** | |
* Add a point for the player. | |
*/ | |
public function score() | |
{ | |
$this->points++; | |
} | |
/** | |
* Convert the player's score to the Tennis term. | |
* | |
* @return string | |
*/ | |
public function toTerm(): string | |
{ | |
switch ($this->points) { | |
case 0: | |
return 'love'; | |
case 1: | |
return 'fifteen'; | |
case 2: | |
return 'thirty'; | |
case 3: | |
return 'forty'; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
class TennisMatch | |
{ | |
/** | |
* @var Player | |
*/ | |
protected Player $playerOne; | |
/** | |
* @var Player | |
*/ | |
protected Player $playerTwo; | |
/** | |
* Create a new TennisMatch. | |
* | |
* @param Player $playerOne | |
* @param Player $playerTwo | |
*/ | |
public function __construct(Player $playerOne, Player $playerTwo) | |
{ | |
$this->playerOne = $playerOne; | |
$this->playerTwo = $playerTwo; | |
} | |
/** | |
* Score the match. | |
* | |
* @return string | |
*/ | |
public function score(): string | |
{ | |
if ($this->hasWinner()) { | |
return 'Winner: '.$this->leader()->name; | |
} | |
if ($this->hasAdvantage()) { | |
return 'Advantage: '.$this->leader()->name; | |
} | |
if ($this->isDeuce()) { | |
return 'deuce'; | |
} | |
return sprintf( | |
"%s-%s", | |
$this->playerOne->toTerm(), | |
$this->playerTwo->toTerm(), | |
); | |
} | |
/** | |
* Get the current leader of the set. | |
* | |
* @return Player | |
*/ | |
protected function leader(): Player | |
{ | |
return $this->playerOne->points > $this->playerTwo->points | |
? $this->playerOne | |
: $this->playerTwo; | |
} | |
/** | |
* Determine if the players are in deuce. | |
* | |
* @return bool | |
*/ | |
protected function isDeuce(): bool | |
{ | |
if (! $this->hasReachedDeuceThreshold()) { | |
return false; | |
} | |
return $this->playerOne->points === $this->playerTwo->points; | |
} | |
/** | |
* Determine if both players have scored at least 3 points. | |
* | |
* @return bool | |
*/ | |
protected function hasReachedDeuceThreshold(): bool | |
{ | |
return $this->playerOne->points >= 3 && $this->playerTwo->points >= 3; | |
} | |
/** | |
* Determine if one player has the advantage. | |
* | |
* @return bool | |
*/ | |
protected function hasAdvantage(): bool | |
{ | |
if (! $this->hasReachedDeuceThreshold()) { | |
return false; | |
} | |
return ! $this->isDeuce(); | |
} | |
/** | |
* Determine if there is a winner. | |
* | |
* @return bool | |
*/ | |
protected function hasWinner(): bool | |
{ | |
if ($this->playerOne->points < 4 && $this->playerTwo->points < 4) { | |
return false; | |
} | |
return abs($this->playerOne->points - $this->playerTwo->points) >= 2; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use App\Player; | |
use App\TennisMatch; | |
use PHPUnit\Framework\TestCase; | |
class TennisMatchTest extends TestCase | |
{ | |
/** | |
* @test | |
* @dataProvider scores | |
*/ | |
function it_scores_a_tennis_match($playerOnePoints, $playerTwoPoints, $score) | |
{ | |
$match = new TennisMatch( | |
$john = new Player('John'), | |
$jane = new Player('Jane'), | |
); | |
for ($i = 0; $i < $playerOnePoints; $i++) { | |
$john->score(); | |
} | |
for ($i = 0; $i < $playerTwoPoints; $i++) { | |
$jane->score(); | |
} | |
$this->assertEquals($score, $match->score()); | |
} | |
public function scores() | |
{ | |
return [ | |
[0, 0, 'love-love'], | |
[1, 0, 'fifteen-love'], | |
[1, 1, 'fifteen-fifteen'], | |
[2, 0, 'thirty-love'], | |
[3, 0, 'forty-love'], | |
[2, 2, 'thirty-thirty'], | |
[3, 3, 'deuce'], | |
[4, 4, 'deuce'], | |
[5, 5, 'deuce'], | |
[4, 3, 'Advantage: John'], | |
[3, 4, 'Advantage: Jane'], | |
[4, 0, 'Winner: John'], | |
[0, 4, 'Winner: Jane'], | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment