diff --git a/README.md b/README.md index 7c5f3ca..93b0351 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 addPlayer('Player', 'player@email.com') +$secretSanta->addPlayer('Player1', 'player1@email.com') ->addPlayer('Player2', 'player2@email.com') ->addCouple('Player3', 'player3@email.com', 'Couple3', 'couple3@email.com') - ->addCouple('Player4', 'player4@email.com', 'Couple4', 'couple4@email.com'); + ->addCouple('Player4', 'player4@email.com', 'Couple4', 'couple4@email.com') + ->addExclusivePlayers( + ['Player5', 'player5@email.com'], + ['Player6', 'player6@email.com'], + ['Player7', 'player7@email.com'], + ['Player8', 'player8@email.com'] + ); foreach ($secretSanta->play() as $player) { echo ("{$player->name()} ({$player->email()}): {$player->secretSanta()->name()}\n"); } ``` +The above example will output: + +```php +Player1 (player1@email.com): Player5 +Player2 (player2@email.com): Player7 +Player3 (player3@email.com): Player2 +Couple3 (couple3@email.com): Player8 +Player4 (player4@email.com): Player3 +Couple4 (couple4@email.com): Player6 +Player5 (player5@email.com): Player4 +Player6 (player6@email.com): Player1 +Player7 (player7@email.com): Couple3 +Player8 (player8@email.com): Couple4 +``` ## License diff --git a/composer.lock b/composer.lock index f49a91a..d3b20e6 100644 --- a/composer.lock +++ b/composer.lock @@ -9,16 +9,16 @@ "packages": [ { "name": "paragonie/random_compat", - "version": "v2.0.3", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "c0125896dbb151380ab47e96c621741e79623beb" + "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c0125896dbb151380ab47e96c621741e79623beb", - "reference": "c0125896dbb151380ab47e96c621741e79623beb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", + "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", "shasum": "" }, "require": { @@ -53,20 +53,20 @@ "pseudorandom", "random" ], - "time": "2016-10-17 15:23:22" + "time": "2016-11-07 23:38:38" }, { "name": "ramsey/uuid", - "version": "3.5.1", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "a07797b986671b0dc823885a81d5e3516b931599" + "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/a07797b986671b0dc823885a81d5e3516b931599", - "reference": "a07797b986671b0dc823885a81d5e3516b931599", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/5677cfe02397dd6b58c861870dfaa5d9007d3954", + "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954", "shasum": "" }, "require": { @@ -79,11 +79,13 @@ "require-dev": { "apigen/apigen": "^4.1", "codeception/aspect-mock": "1.0.0", + "doctrine/annotations": "~1.2.0", "goaop/framework": "1.0.0-alpha.2", "ircmaxell/random-lib": "^1.1", "jakub-onderka/php-parallel-lint": "^0.9.0", "mockery/mockery": "^0.9.4", "moontoast/math": "^1.1", + "php-mock/php-mock-phpunit": "^0.3|^1.1", "phpunit/phpunit": "^4.7|>=5.0 <5.4", "satooshi/php-coveralls": "^0.6.1", "squizlabs/php_codesniffer": "^2.3" @@ -133,7 +135,7 @@ "identifier", "uuid" ], - "time": "2016-10-02 15:51:17" + "time": "2016-11-22 19:21:44" } ], "packages-dev": [ @@ -193,16 +195,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.5.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f" + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", "shasum": "" }, "require": { @@ -231,7 +233,7 @@ "object", "object graph" ], - "time": "2016-09-16 13:37:59" + "time": "2016-10-31 17:19:45" }, { "name": "phpdocumentor/reflection-common", @@ -381,16 +383,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.1", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { @@ -398,10 +400,11 @@ "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { @@ -439,20 +442,20 @@ "spy", "stub" ], - "time": "2016-06-07 08:13:47" + "time": "2016-11-21 14:58:47" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3" + "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d", + "reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d", "shasum": "" }, "require": { @@ -502,7 +505,7 @@ "testing", "xunit" ], - "time": "2016-07-26 14:39:29" + "time": "2016-11-01 05:06:24" }, { "name": "phpunit/php-file-iterator", @@ -638,16 +641,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -683,20 +686,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", - "version": "5.6.2", + "version": "5.6.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01" + "reference": "875145fabfa261fa9c1aea663dd29ddce92dca8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cd13b23ac5a519a4708e00736c26ee0bb28b2e01", - "reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/875145fabfa261fa9c1aea663dd29ddce92dca8f", + "reference": "875145fabfa261fa9c1aea663dd29ddce92dca8f", "shasum": "" }, "require": { @@ -713,12 +716,12 @@ "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "~1.2.2", "sebastian/diff": "~1.2", "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", + "sebastian/exporter": "~2.0", "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", + "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" @@ -765,27 +768,27 @@ "testing", "xunit" ], - "time": "2016-10-25 07:40:25" + "time": "2016-11-21 15:23:34" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.0", + "version": "3.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" + "reference": "45026c8383187ad1dcb14fbfec77dced265b9cfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/45026c8383187ad1dcb14fbfec77dced265b9cfc", + "reference": "45026c8383187ad1dcb14fbfec77dced265b9cfc", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.6 || ^7.0", "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" + "sebastian/exporter": "^1.2 || ^2.0" }, "conflict": { "phpunit/phpunit": "<5.4.0" @@ -824,7 +827,7 @@ "mock", "xunit" ], - "time": "2016-10-09 07:01:45" + "time": "2016-11-19 09:07:46" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -873,22 +876,22 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -933,7 +936,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -1039,21 +1042,21 @@ }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "ext-mbstring": "*", @@ -1062,7 +1065,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1102,7 +1105,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-11-19 08:54:04" }, { "name": "sebastian/global-state", @@ -1157,21 +1160,21 @@ }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "shasum": "" }, "require": { "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "phpunit/phpunit": "~5" @@ -1179,7 +1182,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1199,20 +1202,20 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" + "time": "2016-11-19 07:35:10" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { @@ -1224,7 +1227,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1252,7 +1255,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-11-19 07:33:16" }, { "name": "sebastian/resource-operations", @@ -1341,16 +1344,16 @@ }, { "name": "symfony/yaml", - "version": "v3.1.6", + "version": "v3.1.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" + "reference": "9da375317228e54f4ea1b013b30fa47417e84943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "url": "https://api.github.com/repos/symfony/yaml/zipball/9da375317228e54f4ea1b013b30fa47417e84943", + "reference": "9da375317228e54f4ea1b013b30fa47417e84943", "shasum": "" }, "require": { @@ -1386,7 +1389,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-10-24 18:41:13" + "time": "2016-11-18 21:05:29" }, { "name": "webmozart/assert", diff --git a/src/Exceptions/PlayerException.php b/src/Exceptions/PlayerException.php index 11e415a..fb46689 100644 --- a/src/Exceptions/PlayerException.php +++ b/src/Exceptions/PlayerException.php @@ -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); } } diff --git a/src/Exceptions/PlayersCollectionException.php b/src/Exceptions/PlayersCollectionException.php index 1dc8f72..2a2a8f2 100644 --- a/src/Exceptions/PlayersCollectionException.php +++ b/src/Exceptions/PlayersCollectionException.php @@ -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); } } \ No newline at end of file diff --git a/src/Exceptions/SecretSantaException.php b/src/Exceptions/SecretSantaException.php index bf17a0b..e114541 100644 --- a/src/Exceptions/SecretSantaException.php +++ b/src/Exceptions/SecretSantaException.php @@ -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); } } diff --git a/src/PlayersCollection.php b/src/PlayersCollection.php index b06d562..a5a9597 100644 --- a/src/PlayersCollection.php +++ b/src/PlayersCollection.php @@ -13,7 +13,7 @@ class PlayersCollection implements \Countable /** @var Player[] */ private $players = []; /** @var array */ - private $excludePlayers = []; + private $exclusivePlayers = []; /** * @param Player $player @@ -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[] */ @@ -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(); } } } @@ -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; } @@ -118,9 +137,9 @@ public function count() /** * @return int */ - public function countExcludePlayers() + public function countExclusivePlayers() { - return count($this->excludePlayers); + return count($this->exclusivePlayers); } @@ -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)); } /** diff --git a/src/SecretSanta.php b/src/SecretSanta.php index 3211be6..f7e345b 100644 --- a/src/SecretSanta.php +++ b/src/SecretSanta.php @@ -2,6 +2,7 @@ namespace SecretSanta; +use SecretSanta\Exceptions\PlayerException; use SecretSanta\Exceptions\SecretSantaException; /** @@ -24,6 +25,7 @@ public function __construct() } /** + * Add single player to the game * @param string $name * @param string $email * @return SecretSanta @@ -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 @@ -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 @@ -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); } } @@ -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--; @@ -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; } diff --git a/tests/PlayersCollectionTest.php b/tests/PlayersCollectionTest.php index 0309302..2b1ab73 100644 --- a/tests/PlayersCollectionTest.php +++ b/tests/PlayersCollectionTest.php @@ -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', 'emailSingle@email.com'); $expectedPlayer = Player::create('name', 'email@email.com'); @@ -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@email.com'); + + $playersCollection = new PlayersCollection(); + $playersCollection->addExclusivePlayers( + [$expectedPlayer] + ); + } + + /** + * @expectedException \SecretSanta\Exceptions\PlayersCollectionException + */ + public function AddExclusivePlayersOnlyTwoPlayer() + { + $expectedPlayer = Player::create('name', 'email@email.com'); + $expectedPlayer2 = Player::create('name2', 'email2@email.com'); + + $playersCollection = new PlayersCollection(); + $playersCollection->addExclusivePlayers([ + $expectedPlayer, + $expectedPlayer2 + ]); + } + + public function AddExclusivePlayersThreePlayer() + { + $expectedPlayer = Player::create('name', 'email@email.com'); + $expectedPlayer2 = Player::create('name2', 'email2@email.com'); + $expectedPlayer3 = Player::create('name3', 'email3@email.com'); + + $playersCollection = new PlayersCollection(); + $playersCollection->addExclusivePlayers([ + $expectedPlayer, + $expectedPlayer2, + $expectedPlayer3 + ]); } } \ No newline at end of file diff --git a/tests/SecretSantaTest.php b/tests/SecretSantaTest.php index ce29c80..be6feb7 100644 --- a/tests/SecretSantaTest.php +++ b/tests/SecretSantaTest.php @@ -240,4 +240,104 @@ public function testFiftyCouples() $this->assertSame(100 , count($combination)); } + + /** + * @expectedException \SecretSanta\Exceptions\SecretSantaException + */ + public function testExclusivePlayersEmpty() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers([]); + } + + /** + * @expectedException \SecretSanta\Exceptions\SecretSantaException + */ + public function testExclusivePlayersOnlyOnePlayer() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['Player', 'player@email.com'] + ); + } + + /** + * @expectedException \SecretSanta\Exceptions\SecretSantaException + */ + public function testExclusivePlayersSamePlayer() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['Player', 'player@email.com'], + ['Player', 'player@email.com'] + ); + } + + /** + * @expectedException \SecretSanta\Exceptions\SecretSantaException + */ + public function testExclusivePlayersInvalidPlayer() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['', 'player@email.com'], + ['Player', 'player@email.com'] + ); + } + + /** + * @expectedException \SecretSanta\Exceptions\SecretSantaException + */ + public function testExclusivePlayersTwoPlayers() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['Player', 'player@email.com'], + ['Player2', 'player2@email.com'] + ); + + $secretSanta->play(); + } + + public function testFourExclusivePlayersAndFourSinglePlayers() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['Player', 'player@email.com'], + ['Player2', 'player2@email.com'], + ['Player3', 'player3@email.com'], + ['Player4', 'player4@email.com'] + ); + $secretSanta->addPlayer('Player5', 'player5@email.com'); + $secretSanta->addPlayer('Player6', 'player6@email.com'); + $secretSanta->addPlayer('Player7', 'player7@email.com'); + $secretSanta->addPlayer('Player8', 'player8@email.com'); + + $combination = $secretSanta->play(); + + $this->assertSame(8 , count($combination)); + } + + public function testFourExclusivePlayersAndFourSinglePlayersAndFourCouples() + { + $secretSanta = new SecretSanta(); + $secretSanta->addExclusivePlayers( + ['Player', 'player@email.com'], + ['Player2', 'player2@email.com'], + ['Player3', 'player3@email.com'], + ['Player4', 'player4@email.com'] + ) + ->addPlayer('Player5', 'player5@email.com') + ->addPlayer('Player6', 'player6@email.com') + ->addPlayer('Player7', 'player7@email.com') + ->addPlayer('Player8', 'player8@email.com') + ->addCouple('Player9', 'player9@email.com', 'Couple9', 'couple9@email.com') + ->addCouple('Player10', 'player10@email.com', 'Couple10', 'couple10@email.com') + ->addCouple('Player11', 'player11@email.com', 'Couple11', 'couple11@email.com') + ->addCouple('Player12', 'player12@email.com', 'Couple12', 'couple12@email.com'); + + $combination = $secretSanta->play(); + + $this->assertSame(16 , count($combination)); + } }