Skip to content

Commit

Permalink
Improved combinatorial and minor bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
GuilleGF committed Nov 8, 2016
1 parent ebd4e15 commit 98cfe82
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 35 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

[![Build Status](https://travis-ci.org/GuilleGF/SecretSantaPHP.svg?branch=master)](https://travis-ci.org/GuilleGF/SecretSantaPHP)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/GuilleGF/SecretSantaPHP/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/GuilleGF/SecretSantaPHP/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/GuilleGF/SecretSantaPHP/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/GuilleGF/SecretSantaPHP/?branch=master)
[![Dependency Status](https://www.versioneye.com/user/projects/5821ae0d89f0a91d55eb9600/badge.svg)](https://www.versioneye.com/user/projects/5821ae0d89f0a91d55eb9600)
[![Latest Stable Version](https://poser.pugx.org/guillegf/secret-santa/v/stable)](https://packagist.org/packages/guillegf/secret-santa)
[![Total Downloads](https://poser.pugx.org/guillegf/secret-santa/downloads)](https://packagist.org/packages/guillegf/secret-santa)
[![License](https://poser.pugx.org/guillegf/secret-santa/license)](https://packagist.org/packages/guillegf/secret-santa)

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

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

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

```php
<?php
$secretSanta = new SecretSanta();
$secretSantaPlayers = $secretSanta
->addPlayer('Player', '[email protected]')
->addCouple('Player2', '[email protected]', 'Couple2', '[email protected]')
$secretSanta->addPlayer('Player', '[email protected]')
->addPlayer('Player2', '[email protected]')
->addCouple('Player3', '[email protected]', 'Couple3', '[email protected]')
->play();
->addCouple('Player4', '[email protected]', 'Couple4', '[email protected]');

foreach ($secretSantaPlayers as $player) {
echo ("{$player['name']} {$player['email']}: {$player['secretSanta']}\n");
foreach ($secretSanta->play() as $player) {
echo ("{$player->name()} ({$player->email()}): {$player->secretSanta()->name()}\n");
}
```

Expand Down
41 changes: 41 additions & 0 deletions src/PlayersCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ public function players()
return $this->players;
}

/**
* @return Player[]
*/
public function shufflePlayers()
{
return $this->shuffleAssoc($this->players);
}

/**
* @param string $id
* @return Player
Expand Down Expand Up @@ -117,6 +125,39 @@ private function isDuplicatePlayer(Player $player)
return false;
}

/**
* @param array $list
* @return array
*/
private function shuffleAssoc($list)
{
if (!is_array($list)) return $list;

$keys = $this->forceShuffle(array_keys($list));
$random = [];
foreach ($keys as $key) {
$random[$key] = $list[$key];
}

return $random;
}

/**
* @param array $list
* @return array
*/
private function forceShuffle($list)
{
if (!is_array($list) || count($list) < 2) return $list;

$shuffleList = $list;
while ($shuffleList == $list) {
shuffle($shuffleList);
}

return $shuffleList;
}

/**
* @return Player
*/
Expand Down
53 changes: 27 additions & 26 deletions src/SecretSanta.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,55 +53,56 @@ public function addCouple($name, $email, $coupleName, $coupleEmail)
}

/**
* @return array
* @return PlayersCollection
* @throws SecretSantaException
*/
public function play()
{
$this->combinePlayers();
try {
$this->combinePlayers();

$result = [];
if ($this->isValidCombination()) {
foreach ($this->combination as $playerId => $secretPlayerId) {
$player = $this->players->player($playerId);
$result[] = [
'name' => $player->name(),
'email' => $player->email(),
'secretSanta' => $this->players->player($secretPlayerId)->name()
];
}
return $this->players;
} catch (SecretSantaException $exception) {
throw $exception;
} catch (\Exception $exception) {
throw new SecretSantaException(
'Error during play, impossible to find secret santa, try again',
0,
$exception
);
}

return $result;
}

/**
* @throws SecretSantaException
*/
private function combinePlayers()
{
$retry = 0;
$this->combination = [];
if (count($this->players) < 4) {
throw new SecretSantaException("Not enough players to play, at least 4 players are required");
}

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

while (!$this->isValidCombination() && $retry < (count($this->players)*2)) {
$retry++;
$players = $this->players->players();
$secretPlayers = $this->players->players();
shuffle($players);
shuffle($secretPlayers);
foreach ($players as $player) {
foreach ($secretPlayers as $key => $secretPlayer) {
while (!$this->isValidCombination() && $retry > 0 ) {
$this->combination = [];
$secretPlayers = $this->players->shufflePlayers();
foreach ($this->players as $playerId => $player) {
foreach ($secretPlayers as $secretPlayer) {
if ($player->id() != $secretPlayer->id() && !$this->players->areExclude($player, $secretPlayer)) {
if (!in_array($secretPlayer->id(), $this->combination)) {
$player->setSecretSanta($secretPlayer);
$this->combination[$player->id()] = $secretPlayer->id();
unset ($secretPlayers[$key]);
unset ($secretPlayers[$secretPlayer->id()]);
break;
}
}
}
}
$retry--;
}

if (!$this->isValidCombination()) {
if (!$this->isValidCombination() && $retry <= 0) {
throw new SecretSantaException("Not enough players to play");
}
}
Expand Down
28 changes: 28 additions & 0 deletions tests/PlayerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ public function testSortName()
Player::create('ab', '[email protected]');
}

/**
* @expectedException \SecretSanta\Exceptions\PlayerException
*/
public function testInvalidName()
{
Player::create([], '[email protected]');
}

/**
* @expectedException \SecretSanta\Exceptions\PlayerException
*/
Expand All @@ -31,4 +39,24 @@ public function testPlayer()
$this->assertSame('name', $player->name());
$this->assertSame('[email protected]', $player->email());
}

public function testAddSecretSantaToPlayer()
{
$player = Player::create('name', '[email protected]');
$secretSanta = Player::create('name', '[email protected]');

$player->setSecretSanta($secretSanta);

$this->assertSame($secretSanta, $player->secretSanta());
}

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

$player->secretSanta();
}
}
39 changes: 39 additions & 0 deletions tests/PlayersCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ public function testAddPlayer()
$this->assertSame($expectedPlayer, $player);
}

/**
* @expectedException \SecretSanta\Exceptions\PlayersCollectionException
*/
public function testGetUnKnowPlayer()
{
$expectedPlayer = Player::create('name', '[email protected]');
$playersCollection = new PlayersCollection();
$playersCollection->addPlayer($expectedPlayer);

$playersCollection->player('error-id');
}

/**
* @expectedException \SecretSanta\Exceptions\PlayersCollectionException
*/
Expand All @@ -46,4 +58,31 @@ public function testAddCouple()
$this->assertSame($expectedPlayer, $player);
$this->assertSame($expectedCouple, $couple);
}

public function testShufflePlayers()
{
$expectedPlayer = Player::create('name', '[email protected]');
$expectedCouple = Player::create('nameCouple', '[email protected]');

$playersCollection = new PlayersCollection();
$playersCollection->addCouple($expectedPlayer, $expectedCouple);

$shufflePlayers = $playersCollection->shufflePlayers();

$this->assertNotEquals(array_keys($playersCollection->players()), array_keys($shufflePlayers));
}

public function testExcludePlayers()
{
$expectedSinglePlayer = Player::create('nameSingle', '[email protected]');
$expectedPlayer = Player::create('name', '[email protected]');
$expectedCouple = Player::create('nameCouple', '[email protected]');

$playersCollection = new PlayersCollection();
$playersCollection->addCouple($expectedPlayer, $expectedCouple);

$this->assertTrue($playersCollection->areExclude($expectedPlayer, $expectedCouple));
$this->assertFalse($playersCollection->areExclude($expectedSinglePlayer, $expectedPlayer));
$this->assertSame(2, $playersCollection->countExcludePlayers());
}
}
30 changes: 30 additions & 0 deletions tests/SecretSantaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,34 @@ public function testFourCouplesAndTwoPlayers()

$this->assertSame(10 , count($combination));
}

public function testTenCouplesAndTenPlayers()
{
$secretSanta = new SecretSanta();

$secretSanta->addPlayer('Player', '[email protected]');
$secretSanta->addPlayer('Player2', '[email protected]');
$secretSanta->addCouple('Player3', '[email protected]', 'Couple3', '[email protected]');
$secretSanta->addCouple('Player4', '[email protected]', 'Couple4', '[email protected]');
$secretSanta->addCouple('Player5', '[email protected]', 'Couple5', '[email protected]');
$secretSanta->addCouple('Player6', '[email protected]', 'Couple6', '[email protected]');
$secretSanta->addPlayer('Player7', '[email protected]');
$secretSanta->addPlayer('Player8', '[email protected]');
$secretSanta->addPlayer('Player9', '[email protected]');
$secretSanta->addPlayer('Player10', '[email protected]');
$secretSanta->addPlayer('Player11', '[email protected]');
$secretSanta->addPlayer('Player12', '[email protected]');
$secretSanta->addCouple('Player13', '[email protected]', 'Couple13', '[email protected]');
$secretSanta->addCouple('Player14', '[email protected]', 'Couple14', '[email protected]');
$secretSanta->addCouple('Player15', '[email protected]', 'Couple15', '[email protected]');
$secretSanta->addCouple('Player16', '[email protected]', 'Couple16', '[email protected]');
$secretSanta->addPlayer('Player17', '[email protected]');
$secretSanta->addPlayer('Player18', '[email protected]');
$secretSanta->addCouple('Player19', '[email protected]', 'Couple19', '[email protected]');
$secretSanta->addCouple('Player20', '[email protected]', 'Couple20', '[email protected]');

$combination = $secretSanta->play();

$this->assertSame(30 , count($combination));
}
}

0 comments on commit 98cfe82

Please sign in to comment.