summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFbenas <philbeansburton@gmail.com>2018-05-07 14:42:15 +0100
committerFbenas <philbeansburton@gmail.com>2018-05-07 14:42:15 +0100
commit33f00442f1667d57f94433834e0da4985670025b (patch)
treeaa65df03e719f3d8024b0ea42a62aa7fd61f196e
parentc223ab602cbe7f6db7321ba547164971d63d7bcd (diff)
Get filtering working with output
-rw-r--r--data/input.txt12
-rw-r--r--src/File/Handler.php20
-rw-r--r--src/Model/Collection.php85
-rw-r--r--src/Model/Menu.php38
-rw-r--r--src/Model/Model.php2
-rw-r--r--src/Model/Vendor.php126
-rw-r--r--src/Script/Console.php15
-rw-r--r--src/Script/Input.php27
-rw-r--r--src/Script/Output.php23
9 files changed, 307 insertions, 41 deletions
diff --git a/data/input.txt b/data/input.txt
new file mode 100644
index 0000000..919bc4a
--- /dev/null
+++ b/data/input.txt
@@ -0,0 +1,12 @@
+Grain and Leaf;E32NY;100
+Grain salad;nuts;12h
+
+Wholegrains;SW34DA;20
+The Classic;gluten;24h
+
+Ghana Kitchen;NW42QA;40
+Premium meat selection;;36h
+Breakfast;gluten,eggs;12h
+
+Well Kneaded;EC32BA;150
+Full English breakfast;gluten;24h
diff --git a/src/File/Handler.php b/src/File/Handler.php
index 61c78a8..eecedc0 100644
--- a/src/File/Handler.php
+++ b/src/File/Handler.php
@@ -1,6 +1,6 @@
<?php
-namespace App\File\Handler;
+namespace App\File;
use Exception;
@@ -11,14 +11,13 @@ class Handler
{
protected $filename;
protected $file;
- protected $array;
/**
* Check file can be read
* Read and parse file into array
*
* @author Phil Burton <phil@pgburton.com>
- * @param string $filename [description]
+ * @param string $filename string
*/
public function __construct(string $filename)
{
@@ -26,7 +25,8 @@ class Handler
if (!is_readable($filename)) {
throw new Exception('Cannot read from file: ' . $filename);
}
- $this->load;
+
+ $this->load();
}
/**
@@ -40,17 +40,13 @@ class Handler
}
/**
- * Parse file and return array
+ * Retun the raw file contents
*
* @author Phil Burton <phil@pgburton.com>
- * @return array
+ * @return string
*/
- public function getVendorArray(): array
+ public function getFileContents(): string
{
- if (!$this->array) {
- $this->array = [];
- }
-
- return $this->array;
+ return $this->file;
}
}
diff --git a/src/Model/Collection.php b/src/Model/Collection.php
index 8715f07..803e777 100644
--- a/src/Model/Collection.php
+++ b/src/Model/Collection.php
@@ -4,9 +4,12 @@ namespace App\Model;
use App\Model\Model;
use ArrayAccess;
-use Countable;
use Exception;
use Iterator;
+use App\Script\Input;
+use DateTime;
+use DateTimeZone;
+use Countable;
/**
* A collection of models
@@ -129,7 +132,7 @@ class Collection implements ArrayAccess, Iterator, Countable
* Return true if the current index exists in user array
* Otherwise return false
*
- * @author Phil Burton <phil@pgburton.com>
+ * @author Phil Burton <phil@pgburton.com>"dump"
* @return bool
*/
public function valid()
@@ -169,24 +172,78 @@ class Collection implements ArrayAccess, Iterator, Countable
}
/**
- * Create and return new collection of the merged arrays from thsi and a given collection
+ * Filter by input
*
* @author Phil Burton <phil@pgburton.com>
- * @param Collection $collection
- * @return Collection
+ * @param Input $input
*/
- public function merge(Collection $collection): Collection
+ public function filterByInput(Input $input)
{
- return new Collection(array_merge($collection->toArray(), $this->toArray()));
+ // filter by time
+ if ($time = $input->getOption('t')) {
+ $day = $input->getOption('d');
+ $this->filterByDateTime($day, $time);
+ }
+
+ if ($location = $input->getOption('l')) {
+ $this->filterByLocation($location);
+ }
+
+ if ($covers = (int) $input->getOption('c')) {
+ $this->filterByCovers($covers);
+ }
+
+
+ // day - delivery day (dd/mm/yy)
+ // time - delivery time in 24h format (hh:mm)
+ // location - delivery location (postcode without spaces, e.g. NW43QB)
+ // covers - number of people to feed
}
- /**
- * Return count of users
- *
- * @author Phil Burton <phil@pgburton.com>
- * @return int
- */
- public function count(): int
+ public function filterByDateTime(string $date, string $time)
+ {
+ $dateTime = DateTime::createFromFormat('d/m/y G:i', $date . ' ' . $time);
+ $dateTime->setTImezone(new DateTImeZone('Europe/London'));
+
+ $out = [];
+ foreach ($this->models as $model) {
+ if ($model->checkDate($dateTime)) {
+ $out[] = $model;
+ }
+ }
+
+ $this->models = $out;
+ }
+
+ public function filterByLocation(string $location)
+ {
+ $location = substr($location, 0, 2);
+
+ $out = [];
+
+ foreach ($this->models as $model) {
+ if ($model->checkLocation($location)) {
+ $out[] = $model;
+ }
+ }
+
+ $this->models = $out;
+ }
+
+ public function filterByCovers(int $covers)
+ {
+ $out = [];
+
+ foreach ($this->models as $model) {
+ if ($model->checkMaxCovers($covers)) {
+ $out[] = $model;
+ }
+ }
+
+ $this->models = $out;
+ }
+
+ public function count()
{
return count($this->models);
}
diff --git a/src/Model/Menu.php b/src/Model/Menu.php
index e69de29..d0a281e 100644
--- a/src/Model/Menu.php
+++ b/src/Model/Menu.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Model;
+
+use App\Model\Model;
+
+/**
+ * Menu Model
+ */
+class Menu extends Model
+{
+ protected $name;
+ protected $allergies;
+ protected $advanceTime;
+
+
+ public function __construct($name, $allergies, $advanceTime)
+ {
+ $this->name = $name;
+ $this->allergies = $allergies;
+ $this->setTime($advanceTime);
+ }
+
+ public function setTime($time)
+ {
+ $this->advanceTime = str_replace('h', '', $time);
+ }
+
+ public function getAdvanceTime(): int
+ {
+ return $this->advanceTime;
+ }
+
+ public function toString()
+ {
+ return $this->name . ';' . $this->allergies;
+ }
+}
diff --git a/src/Model/Model.php b/src/Model/Model.php
index 99847f9..f59ab0e 100644
--- a/src/Model/Model.php
+++ b/src/Model/Model.php
@@ -7,6 +7,8 @@ namespace App\Model;
*/
class Model
{
+ protected static $inputFile = APP_ROOT . 'data/input.txt';
+
/**
* Init
*
diff --git a/src/Model/Vendor.php b/src/Model/Vendor.php
index 99a95dd..6b98704 100644
--- a/src/Model/Vendor.php
+++ b/src/Model/Vendor.php
@@ -4,8 +4,10 @@ namespace App\Model;
use App\File\Handler as FileHandler;
use App\Model\Collection;
+use App\Model\Menu;
use App\Model\Model;
-use App\Script\Input;
+use DateTime;
+use DateInterval;
/**
* Vendor Model
@@ -17,6 +19,19 @@ class Vendor extends Model
protected $maxCovers;
protected $menus;
+ public function __construct($name, $postcode, $maxCovers)
+ {
+ $this->name = $name;
+ $this->postcode = $postcode;
+ $this->maxCovers = $maxCovers;
+ $this->menus = [];
+ }
+
+ public function addMenu(Menu $menu)
+ {
+ $this->menus[] = $menu;
+ }
+
/**
* Load vendors from file, parse them into a model collection and Return
*
@@ -36,14 +51,115 @@ class Vendor extends Model
return $collection;
}
+ public static function loadAll(string $filename): Collection
+ {
+ $fileHandler = new FileHandler($filename);
+
+ $fileContents = $fileHandler->getFileContents();
+
+ return static::parseVendors($fileContents);
+ }
+
+
/**
- * Filter by input
+ * Parse file and return array
*
* @author Phil Burton <phil@pgburton.com>
- * @param Input $input
+ * @return array
*/
- public function filterByInput(Input $input)
+ public static function parseVendors($fileContents): Collection
+ {
+ $collection = new Collection;
+
+ // split the various vendor data out
+ $array = explode("\n\n", $fileContents);
+
+ // For each vendor
+ foreach ($array as $value) {
+ $rawVendor = explode("\n", $value);
+ // Split off the vendor data
+ $vendorHead = explode(";", $rawVendor[0]);
+
+ $vendor = new Vendor($vendorHead[0], $vendorHead[1], $vendorHead[2]);
+
+ // Remove the head
+ unset($rawVendor[0]);
+ // Reset the keys
+ $rawVendor = array_values($rawVendor);
+
+ // Now parse menus
+ foreach ($rawVendor as $item) {
+ // Ignore empty line (usually last line of file)
+ if ($item === "") {
+ continue;
+ }
+ $rawMenu = explode(";", $item);
+ $menu = new Menu($rawMenu[0], $rawMenu[1], $rawMenu[2]);
+ $vendor->addMenu($menu);
+ }
+
+ $collection[] = $vendor;
+ }
+
+ return $collection;
+ }
+
+ public function checkDate(DateTime $date)
{
- // Amend the colletion so we've filtered by the input
+ $out = [];
+ $now = new DateTime();
+
+ foreach ($this->menus as $menu) {
+ $earliestDelivery = $now->add(new DateInterval('PT' . $menu->getAdvanceTime() . 'H'));
+
+ if ($earliestDelivery <= $date) {
+ $out[] = $menu;
+ }
+ }
+
+ $this->menus = $out;
+
+ if (!$this->menus) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function checkLocation(string $location)
+ {
+ $postPrefix = '';
+
+ foreach (str_split($this->postcode) as $char) {
+ if (is_numeric($char)) {
+ break;
+ }
+
+ $postPrefix .= $char;
+ }
+
+ return strtoupper($postPrefix) === strtoupper($location);
+ }
+
+ public function checkMaxCovers(int $covers)
+ {
+ if ($this->maxCovers >= $covers) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function toString()
+ {
+ $out = [
+ $this->name . ';' . $this->postcode . ';' . $this->maxCovers
+ ];
+
+ foreach ($this->menus as $menu) {
+ $out[] = $menu->toString();
+ }
+
+ return $out;
}
}
diff --git a/src/Script/Console.php b/src/Script/Console.php
index bedbc1d..e1d7df5 100644
--- a/src/Script/Console.php
+++ b/src/Script/Console.php
@@ -2,9 +2,9 @@
namespace App\Script;
-// use App\Model\Vendor;
+use App\Model\Vendor;
use App\Script\Input;
-// use App\Script\Output;
+use App\Script\Output;
/**
* Main application class
@@ -32,6 +32,9 @@ class Console
{
// Define the root of the application
define('APP_ROOT', realpath(dirname(__FILE__) . '/../../') . '/');
+
+ // Set default tiemzone
+ date_default_timezone_set('Europe/London');
}
/**
@@ -41,12 +44,12 @@ class Console
*/
public function exec()
{
- $vendors = Vendor::loadAll();
$input = new Input;
+ $vendors = Vendor::loadAll($input->getOption('f'));
$vendors->filterByInput($input);
- // $output = new Output;
- //
- // $output->printCollection($vendors);
+
+ $output = new Output;
+ $output->printCollection($vendors);
}
}
diff --git a/src/Script/Input.php b/src/Script/Input.php
index 6b15c51..4e437dd 100644
--- a/src/Script/Input.php
+++ b/src/Script/Input.php
@@ -19,7 +19,15 @@ class Input
*
* @var string
*/
- protected $availableOptions = 'fdtlc::';
+ protected $shortOpts = 'f:d::t::l::c::';
+
+ protected $longOpts = [
+ 'filename:',
+ 'day::',
+ 'time::',
+ 'location::',
+ 'covers::'
+ ];
/**
* The loaded CLI options
@@ -45,7 +53,7 @@ class Input
*/
protected function loadOptions()
{
- $this->options = getopt($this->getOptionString());
+ $this->options = getopt($this->getShortOptionString(), $this->getLongOptionString());
if (!array_key_exists('f', $this->options)) {
throw new Exception('Filename Option `-f` is required');
@@ -63,9 +71,20 @@ class Input
* @author Phil Burton <phil@pgburton.com>
* @return string
*/
- public function getOptionString(): string
+ public function getShortOptionString(): string
+ {
+ return $this->shortOpts;
+ }
+
+ /**
+ * Return the option string for the options we want to load
+ *
+ * @author Phil Burton <phil@pgburton.com>
+ * @return string
+ */
+ public function getLongOptionString(): array
{
- return $this->availableOptions;
+ return $this->longOpts;
}
/**
diff --git a/src/Script/Output.php b/src/Script/Output.php
index e69de29..8f7a689 100644
--- a/src/Script/Output.php
+++ b/src/Script/Output.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Script;
+
+use App\Model\Collection;
+
+class Output
+{
+ public function printCollection(Collection $collection)
+ {
+ if (count($collection) === 0) {
+ echo "No results found\n";
+ return;
+ }
+
+ $out = [];
+ foreach ($collection as $vendor) {
+ $out[] = implode("\n", $vendor->toString());
+ }
+
+ echo implode("\n\n", $out) . "\n";
+ }
+}