Merge branch 'picker-service'
This commit is contained in:
commit
53e69067e4
|
@ -6,6 +6,7 @@
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"guzzlehttp/guzzle": "^6.3",
|
"guzzlehttp/guzzle": "^6.3",
|
||||||
|
"josephlavin/tap": "^1.0",
|
||||||
"symfony/cache": "4.2.*",
|
"symfony/cache": "4.2.*",
|
||||||
"symfony/console": "4.2.*",
|
"symfony/console": "4.2.*",
|
||||||
"symfony/dotenv": "4.2.*",
|
"symfony/dotenv": "4.2.*",
|
||||||
|
|
41
composer.lock
generated
41
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "15c99cfaa96233a5a12cf632ac267c27",
|
"content-hash": "35f8b30095e57576a83ae4bdaa898a19",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
|
@ -189,6 +189,45 @@
|
||||||
],
|
],
|
||||||
"time": "2018-12-04T20:46:45+00:00"
|
"time": "2018-12-04T20:46:45+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "josephlavin/tap",
|
||||||
|
"version": "v1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/josephlavin/tap.git",
|
||||||
|
"reference": "8733d96fb9b7d7dca204dfe59ec3ff34f3c69be9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/josephlavin/tap/zipball/8733d96fb9b7d7dca204dfe59ec3ff34f3c69be9",
|
||||||
|
"reference": "8733d96fb9b7d7dca204dfe59ec3ff34f3c69be9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~5.7"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/tap.php",
|
||||||
|
"src/TapProxy.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Stand alone port of Laravel's tap method.",
|
||||||
|
"keywords": [
|
||||||
|
"laravel",
|
||||||
|
"php",
|
||||||
|
"tap"
|
||||||
|
],
|
||||||
|
"time": "2017-09-24T23:36:28+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/cache",
|
"name": "psr/cache",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Command;
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\Picker;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Symfony\Component\Cache\Simple\FilesystemCache;
|
use Symfony\Component\Cache\Simple\FilesystemCache;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
@ -19,10 +20,22 @@ class PickWinnerCommand extends Command
|
||||||
*/
|
*/
|
||||||
private $client;
|
private $client;
|
||||||
|
|
||||||
public function __construct()
|
/**
|
||||||
|
* @var \App\Service\Picker
|
||||||
|
*/
|
||||||
|
private $picker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PickWinnerCommand constructor.
|
||||||
|
*
|
||||||
|
* @param \App\Service\Picker $picker
|
||||||
|
* The Picker service.
|
||||||
|
*/
|
||||||
|
public function __construct(Picker $picker)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->client = new Client();
|
$this->client = new Client();
|
||||||
|
$this->picker = $picker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
113
src/Service/Picker.php
Normal file
113
src/Service/Picker.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Tightenco\Collect\Support\Collection;
|
||||||
|
|
||||||
|
class Picker
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The combined hosts for the retrieved events.
|
||||||
|
*
|
||||||
|
* @var \Tightenco\Collect\Support\Collection
|
||||||
|
*/
|
||||||
|
private $hosts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Tightenco\Collect\Support\Collection
|
||||||
|
*/
|
||||||
|
private $comments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picker constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->comments = collect();
|
||||||
|
$this->hosts = collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the combined comments for all events.
|
||||||
|
*
|
||||||
|
* @return \Tightenco\Collect\Support\Collection
|
||||||
|
*/
|
||||||
|
public function getComments(): Collection
|
||||||
|
{
|
||||||
|
return $this->comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the event hosts.
|
||||||
|
*
|
||||||
|
* @return \Tightenco\Collect\Support\Collection
|
||||||
|
*/
|
||||||
|
public function getHosts(): Collection
|
||||||
|
{
|
||||||
|
return $this->hosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the hosts for the retrieved events.
|
||||||
|
*
|
||||||
|
* @param \Tightenco\Collect\Support\Collection $data
|
||||||
|
* The event data.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setHosts(Collection $data): self
|
||||||
|
{
|
||||||
|
$this->hosts = $data->pluck('hosts.*.host_name')
|
||||||
|
->flatten(1)
|
||||||
|
->unique()
|
||||||
|
->sort();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the comments for the events.
|
||||||
|
*
|
||||||
|
* @param \Tightenco\Collect\Support\Collection $comments
|
||||||
|
* A collection of comments.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setComments(Collection $comments): self
|
||||||
|
{
|
||||||
|
$this->comments = $comments
|
||||||
|
->flatten(1)
|
||||||
|
->filter(function (array $comment) {
|
||||||
|
return !$this->isUserAnEventHost($comment['user_display_name']);
|
||||||
|
})
|
||||||
|
->values();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a commenter is an event host.
|
||||||
|
*
|
||||||
|
* @param string $user_display_name
|
||||||
|
* The user's display name.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isUserAnEventHost(string $user_display_name): bool
|
||||||
|
{
|
||||||
|
return $this->hosts->contains($user_display_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select and return the winners.
|
||||||
|
*
|
||||||
|
* @param int $count
|
||||||
|
* The number of winners.
|
||||||
|
*
|
||||||
|
* @return \Tightenco\Collect\Support\Collection
|
||||||
|
*/
|
||||||
|
public function getWinners(int $count): Collection
|
||||||
|
{
|
||||||
|
return $this->getComments()->random($count);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,9 @@
|
||||||
"guzzlehttp/psr7": {
|
"guzzlehttp/psr7": {
|
||||||
"version": "1.5.2"
|
"version": "1.5.2"
|
||||||
},
|
},
|
||||||
|
"josephlavin/tap": {
|
||||||
|
"version": "v1.0.0"
|
||||||
|
},
|
||||||
"nikic/php-parser": {
|
"nikic/php-parser": {
|
||||||
"version": "v4.2.0"
|
"version": "v4.2.0"
|
||||||
},
|
},
|
||||||
|
|
141
tests/Service/PickerTest.php
Normal file
141
tests/Service/PickerTest.php
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Service;
|
||||||
|
|
||||||
|
use App\Service\Picker;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Tightenco\Collect\Support\Collection;
|
||||||
|
|
||||||
|
class PickerTest extends TestCase
|
||||||
|
{
|
||||||
|
/** @test */
|
||||||
|
public function hosts_for_multiple_events_are_grouped_and_unique()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
[
|
||||||
|
'hosts' => [
|
||||||
|
['host_name' => 'Lee Stone'],
|
||||||
|
['host_name' => 'Dave Liddament'],
|
||||||
|
['host_name' => 'Kat Zien'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'hosts' => [
|
||||||
|
['host_name' => 'Oliver Davies'],
|
||||||
|
['host_name' => 'Lee Stone'],
|
||||||
|
['host_name' => 'Lucia Velasco'],
|
||||||
|
['host_name' => 'Dave Liddament'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$hosts = (new Picker())
|
||||||
|
->setHosts(collect($data))
|
||||||
|
->getHosts();
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Collection::class, $hosts);
|
||||||
|
$this->assertCount(5, $hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function comments_for_multiple_events_are_flattened_and_combined()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'comment' => 'Great talk!',
|
||||||
|
'user_display_name' => 'Dan Ackroyd',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'comment' => 'Could be better.',
|
||||||
|
'user_display_name' => 'Lucia Velasco',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'comment' => 'Needs more cat pictures.',
|
||||||
|
'user_display_name' => 'Rupert Jabelman',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$comments = (new Picker())
|
||||||
|
->setComments(collect($data))
|
||||||
|
->getComments();
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Collection::class, $comments);
|
||||||
|
$this->assertCount(3, $comments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function comments_from_event_hosts_cannot_be_picked()
|
||||||
|
{
|
||||||
|
$event = [
|
||||||
|
'hosts' => [
|
||||||
|
['host_name' => 'Oliver Davies'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$comments = [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'comment' => 'Great talk!',
|
||||||
|
'user_display_name' => 'Peter Fisher',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'comment' => 'Text on slides could be bigger.',
|
||||||
|
'user_display_name' => 'Oliver Davies',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'comment' => 'Speak slower.',
|
||||||
|
'user_display_name' => 'Zan Baldwin',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$comments = (new Picker())
|
||||||
|
->setHosts(collect([$event]))
|
||||||
|
->setComments(collect($comments))
|
||||||
|
->getComments();
|
||||||
|
|
||||||
|
$this->assertCount(2, $comments);
|
||||||
|
$this->assertSame('Peter Fisher', $comments[0]['user_display_name']);
|
||||||
|
$this->assertSame('Zan Baldwin', $comments[1]['user_display_name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function winners_can_be_selected()
|
||||||
|
{
|
||||||
|
$comments = [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'comment' => 'Great talk!',
|
||||||
|
'user_display_name' => 'Peter Fisher',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'comment' => 'Text on slides could be bigger.',
|
||||||
|
'user_display_name' => 'Michael Bush',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'comment' => 'Speak slower.',
|
||||||
|
'user_display_name' => 'Zan Baldwin',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$picker = new Picker();
|
||||||
|
$picker->setComments(collect($comments));
|
||||||
|
$this->assertCount(3, $picker->getComments());
|
||||||
|
|
||||||
|
tap($picker->getWinners(1), function (Collection $winners) use ($picker) {
|
||||||
|
$this->assertCount(1, $winners);
|
||||||
|
$this->assertTrue($picker->getComments()->contains($winners->first()));
|
||||||
|
});
|
||||||
|
|
||||||
|
tap($picker->getWinners(2), function (Collection $winners) use ($picker) {
|
||||||
|
$this->assertCount(2, $winners);
|
||||||
|
$this->assertTrue($picker->getComments()->contains($winners->first()));
|
||||||
|
$this->assertTrue($picker->getComments()->contains($winners->last()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue