Skip to content

Commit

Permalink
Add multiple exclusive players
Browse files Browse the repository at this point in the history
  • Loading branch information
GuilleGF committed Nov 23, 2016
1 parent 3416fc6 commit a933620
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 37 deletions.
34 changes: 29 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
[![License](https://poser.pugx.org/guillegf/secret-santa/license)](https://packagist.org/packages/guillegf/secret-santa)

* Repository: https://github.com/GuilleGF/SecretSantaPHP
* Version: 1.1.1
* Version: 1.2.0
* License: MIT, see [LICENSE](LICENSE)

## Description
Expand All @@ -31,29 +31,53 @@ documentation.
To add this dependency using the command, run the following from within your
project directory:
```
composer require guillegf/secret-santa "~1.1"
composer require guillegf/secret-santa "~1.2"
```

Alternatively, add the dependency directly to your `composer.json` file:
```json
"require": {
"guillegf/secret-santa": "~1.1"
"guillegf/secret-santa": "~1.2"
}
```
## Usage

In this example in total we add 10 players, 2 singles players, 2 couples (exclusive) and 4 exclusive players.

**The couples and exclusive players never match together.**

```php
<?php
$secretSanta = new SecretSanta();
$secretSanta->addPlayer('Player', 'player@email.com')
$secretSanta->addPlayer('Player1', 'player1@email.com')
->addPlayer('Player2', '[email protected]')
->addCouple('Player3', '[email protected]', 'Couple3', '[email protected]')
->addCouple('Player4', '[email protected]', 'Couple4', '[email protected]');
->addCouple('Player4', '[email protected]', 'Couple4', '[email protected]')
->addExclusivePlayers(
['Player5', '[email protected]'],
['Player6', '[email protected]'],
['Player7', '[email protected]'],
['Player8', '[email protected]']
);

foreach ($secretSanta->play() as $player) {
echo ("{$player->name()} ({$player->email()}): {$player->secretSanta()->name()}\n");
}
```
The above example will output:

```php
Player1 ([email protected]): Player5
Player2 ([email protected]): Player7
Player3 ([email protected]): Player2
Couple3 ([email protected]): Player8
Player4 ([email protected]): Player3
Couple4 ([email protected]): Player6
Player5 ([email protected]): Player4
Player6 ([email protected]): Player1
Player7 ([email protected]): Couple3
Player8 ([email protected]): Couple4
```

## License

Expand Down
5 changes: 2 additions & 3 deletions src/Exceptions/PlayerException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ class PlayerException extends \Exception
/**
* PlayerException constructor.
* @param string $message
* @param int $code
* @param \Exception|null $previous
*/
public function __construct($message, $code = 0, \Exception $previous = null)
public function __construct($message, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
parent::__construct($message, 0, $previous);
}
}
5 changes: 2 additions & 3 deletions src/Exceptions/PlayersCollectionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ class PlayersCollectionException extends \Exception
/**
* PlayersCollectionException constructor.
* @param string $message
* @param int $code
* @param \Exception|null $previous
*/
public function __construct($message, $code = 0, \Exception $previous = null)
public function __construct($message, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
parent::__construct($message, 0, $previous);
}
}
5 changes: 2 additions & 3 deletions src/Exceptions/SecretSantaException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ class SecretSantaException extends \Exception
/**
* SecretSantaException constructor.
* @param string $message
* @param int $code
* @param \Exception|null $previous
*/
public function __construct($message, $code = 0, \Exception $previous = null)
public function __construct($message, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
parent::__construct($message, 0, $previous);
}
}
55 changes: 39 additions & 16 deletions src/PlayersCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PlayersCollection implements \Countable
/** @var Player[] */
private $players = [];
/** @var array */
private $excludePlayers = [];
private $exclusivePlayers = [];

/**
* @param Player $player
Expand All @@ -33,18 +33,37 @@ public function addPlayer(Player $player)
*/
public function addCouple(Player $player, Player $couple)
{
if (!$this->areDifferentPlayers($player, $couple)) {
throw new PlayersCollectionException('The couple can not be the same player');
if (!$this->areDifferentPlayers([$player, $couple])) {
throw new PlayersCollectionException('The couple can not be the same player');
}

if (!$this->isDuplicatePlayer($player) && !$this->isDuplicatePlayer($couple) ) {
$this->players[$player->id()] = $player;
$this->players[$couple->id()] = $couple;

$this->excludePlayers($player, $couple);
$this->exclusivePlayers([$player, $couple]);
}
}

/**
* @param Player[] $players
* @throws PlayersCollectionException
*/
public function addExclusivePlayers($players)
{
if (!$this->areDifferentPlayers($players)) {
throw new PlayersCollectionException('The players must be different');
}

foreach ($players as $player) {
if (!$this->isDuplicatePlayer($player)) {
$this->players[$player->id()] = $player;
}
}

$this->exclusivePlayers($players);
}

/**
* @return Player[]
*/
Expand Down Expand Up @@ -77,16 +96,16 @@ public function player($id)


/**
* @param Player[] ...$players
* @param Player[] $players
*/
private function excludePlayers(...$players)
private function exclusivePlayers($players)
{
foreach ($players as $mainPlayer) {
foreach ($players as $player) {
if ($mainPlayer->id() == $player->id()){
continue;
}
$this->excludePlayers[$mainPlayer->id()][] = $player->id();
$this->exclusivePlayers[$mainPlayer->id()][] = $player->id();
}
}
}
Expand All @@ -96,10 +115,10 @@ private function excludePlayers(...$players)
* @param Player $player2
* @return bool
*/
public function areExclude(Player $player, Player $player2)
public function areExclusive(Player $player, Player $player2)
{
if (array_key_exists($player->id(), $this->excludePlayers)
&& in_array($player2->id(), $this->excludePlayers[$player->id()])
if (array_key_exists($player->id(), $this->exclusivePlayers)
&& in_array($player2->id(), $this->exclusivePlayers[$player->id()])
) {
return true;
}
Expand All @@ -118,9 +137,9 @@ public function count()
/**
* @return int
*/
public function countExcludePlayers()
public function countExclusivePlayers()
{
return count($this->excludePlayers);
return count($this->exclusivePlayers);
}


Expand All @@ -139,13 +158,17 @@ private function isDuplicatePlayer(Player $player)
}

/**
* @param Player $player
* @param Player $otherPlayer
* @param Player[] $players
* @return bool
*/
private function areDifferentPlayers(Player $player, Player $otherPlayer)
private function areDifferentPlayers($players)
{
return $player->id() != $otherPlayer->id();
$uniqueIds = [];
foreach ($players as $player) {
$uniqueIds[] = $player->id();
}

return count($players) == count(array_unique($uniqueIds));
}

/**
Expand Down
38 changes: 35 additions & 3 deletions src/SecretSanta.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SecretSanta;

use SecretSanta\Exceptions\PlayerException;
use SecretSanta\Exceptions\SecretSantaException;

/**
Expand All @@ -24,6 +25,7 @@ public function __construct()
}

/**
* Add single player to the game
* @param string $name
* @param string $email
* @return SecretSanta
Expand All @@ -36,6 +38,7 @@ public function addPlayer($name, $email)
}

/**
* Add two excluded players to the game
* @param string $name
* @param string $email
* @param string $coupleName
Expand All @@ -52,6 +55,35 @@ public function addCouple($name, $email, $coupleName, $coupleEmail)
return $this;
}

/**
* Add multiple exclusive players to the game
* @param array $playersData
* @return $this
* @throws SecretSantaException
*/
public function addExclusivePlayers(...$playersData)
{
if (count($playersData) < 2) {
throw new SecretSantaException('Number of players must be grater or equal than two.');
}

try {
$players = [];
foreach ($playersData as $playerData) {
list($name, $email) = array_values($playerData);
$players[] = Player::create($name, $email);
}

$this->players->addExclusivePlayers($players);
} catch (PlayerException $exception) {
throw new SecretSantaException('One o more players are invalids.', $exception);
} catch (\Exception $exception) {
throw new SecretSantaException('An error has occurred.', $exception);
}

return $this;
}

/**
* @return Player[]
* @throws SecretSantaException
Expand All @@ -65,7 +97,7 @@ public function play()
} catch (SecretSantaException $exception) {
throw $exception;
} catch (\Exception $exception) {
throw new SecretSantaException('Error during play, impossible to find secret santa, try again');
throw new SecretSantaException('Error during play, impossible to find secret santa, try again', $exception);
}
}

Expand All @@ -78,7 +110,7 @@ private function combinePlayers()
throw new SecretSantaException("Not enough players to play, at least 4 players are required");
}

$retry = count($this->players) + $this->players->countExcludePlayers();
$retry = count($this->players) + $this->players->countExclusivePlayers();

while (!$this->tryMatchSecretSantaPlayers() && $retry > 0 ) {
$retry--;
Expand Down Expand Up @@ -116,7 +148,7 @@ private function tryMatchSecretSantaPlayers()
*/
private function isValidSecretSanta($player, $secretPlayer)
{
if ($player->id() != $secretPlayer->id() && !$this->players->areExclude($player, $secretPlayer)) {
if ($player->id() != $secretPlayer->id() && !$this->players->areExclusive($player, $secretPlayer)) {
if (!in_array($secretPlayer->id(), $this->combination)) {
return true;
}
Expand Down
59 changes: 55 additions & 4 deletions tests/PlayersCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function testShufflePlayers()
$this->assertNotEquals(array_keys($playersCollection->players()), array_keys($shufflePlayers));
}

public function testExcludePlayers()
public function testExclusivePlayers()
{
$expectedSinglePlayer = Player::create('nameSingle', '[email protected]');
$expectedPlayer = Player::create('name', '[email protected]');
Expand All @@ -105,8 +105,59 @@ public function testExcludePlayers()
$playersCollection = new PlayersCollection();
$playersCollection->addCouple($expectedPlayer, $expectedCouple);

$this->assertTrue($playersCollection->areExclude($expectedPlayer, $expectedCouple));
$this->assertFalse($playersCollection->areExclude($expectedSinglePlayer, $expectedPlayer));
$this->assertSame(2, $playersCollection->countExcludePlayers());
$this->assertTrue($playersCollection->areExclusive($expectedPlayer, $expectedCouple));
$this->assertFalse($playersCollection->areExclusive($expectedSinglePlayer, $expectedPlayer));
$this->assertSame(2, $playersCollection->countExclusivePlayers());
}

/**
* @expectedException \SecretSanta\Exceptions\PlayersCollectionException
*/
public function AddExclusivePlayersEmpty()
{
$playersCollection = new PlayersCollection();
$playersCollection->addExclusivePlayers([]);
}

/**
* @expectedException \SecretSanta\Exceptions\PlayersCollectionException
*/
public function AddExclusivePlayersOnlyOnePlayer()
{
$expectedPlayer = Player::create('name', '[email protected]');

$playersCollection = new PlayersCollection();
$playersCollection->addExclusivePlayers(
[$expectedPlayer]
);
}

/**
* @expectedException \SecretSanta\Exceptions\PlayersCollectionException
*/
public function AddExclusivePlayersOnlyTwoPlayer()
{
$expectedPlayer = Player::create('name', '[email protected]');
$expectedPlayer2 = Player::create('name2', '[email protected]');

$playersCollection = new PlayersCollection();
$playersCollection->addExclusivePlayers([
$expectedPlayer,
$expectedPlayer2
]);
}

public function AddExclusivePlayersThreePlayer()
{
$expectedPlayer = Player::create('name', '[email protected]');
$expectedPlayer2 = Player::create('name2', '[email protected]');
$expectedPlayer3 = Player::create('name3', '[email protected]');

$playersCollection = new PlayersCollection();
$playersCollection->addExclusivePlayers([
$expectedPlayer,
$expectedPlayer2,
$expectedPlayer3
]);
}
}
Loading

0 comments on commit a933620

Please sign in to comment.