From 33f00442f1667d57f94433834e0da4985670025b Mon Sep 17 00:00:00 2001 From: Fbenas Date: Mon, 7 May 2018 14:42:15 +0100 Subject: Get filtering working with output --- src/File/Handler.php | 20 +++----- src/Model/Collection.php | 85 ++++++++++++++++++++++++++------ src/Model/Menu.php | 38 ++++++++++++++ src/Model/Model.php | 2 + src/Model/Vendor.php | 126 +++++++++++++++++++++++++++++++++++++++++++++-- src/Script/Console.php | 15 +++--- src/Script/Input.php | 27 ++++++++-- src/Script/Output.php | 23 +++++++++ 8 files changed, 295 insertions(+), 41 deletions(-) (limited to 'src') 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 @@ - * @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 - * @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 + * @author Phil Burton "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 - * @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 - * @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 @@ +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 - * @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 * @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 + * @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 @@ +toString()); + } + + echo implode("\n\n", $out) . "\n"; + } +} -- cgit v1.2.3