Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ Lets start with an simple version implementation and grow from it.
php src/prompt.php
```


___With Docker ___
***With Docker***

```bash
docker run --rm -ti -v $(pwd):/app -w /app composer:latest /app/scripts/run_in_docker.sh
Expand Down Expand Up @@ -46,6 +45,13 @@ I think the code and git log will give a lot of insight of why/how i did X in th
- Normally in large code bases i work using the git-flow approach but for small repos/projects, working alone and in the begin of the project i dont use it to remove the overhead of it, that is why in most of this project i didn't use it.
- I have use PHPUnit for some time, but i dont really like the way the testing API is done, that is why i use atoum, which i found more expresive, and easy to understand at first look

# Info

The SERVICE option has been implemented as a different shell with its own commands the commands so far are

- Info
- exit


# Extras

Expand Down Expand Up @@ -78,7 +84,6 @@ Setup a VendingMachine class with the basic funcionality I/O (Simple version to

- [ ] Cleaning tests


### Interfaces

#### Terminal UI
Expand Down
2 changes: 1 addition & 1 deletion src/Checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function __construct(CoinManager $coinManager, Products $products)
public function sell(string $productCode, array &$money)
{
$product = $this->products->find($productCode);
if (!$product->any()) {
if ($product == null || !$product->any()) {
throw new \Exception("Product $productCode not available", 11);
}

Expand Down
5 changes: 5 additions & 0 deletions src/CoinManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,9 @@ public function add(...$coins)

return true;
}

public function getCoins()
{
return $this->coinDrawers;
}
}
111 changes: 0 additions & 111 deletions src/ConsoleUI.php

This file was deleted.

21 changes: 21 additions & 0 deletions src/VendingMachine.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class VendingMachine
private $insertedCoins = [];
private $products = null;
private $checkout;
private $service = false;


public function __construct(CoinManager $coinManager, Products $products)
Expand Down Expand Up @@ -53,4 +54,24 @@ public function sellProduct(string $productCode) : array

return [$product, $this->returnCoins()];
}

public function setService(bool $status)
{
$this->service = $status;
}

public function inService(): bool
{
return $this->service;
}

public function getCoinManager()
{
return $this->coinManager;
}

public function getProducts()
{
return $this->products;
}
}
5 changes: 5 additions & 0 deletions src/models/generic/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public function getIterator()
return new \ArrayIterator($this->items->toArray());
}

public function toArray()
{
return $this->items->toArray();
}

private function internalSort()
{
$this->items->sort(function ($a, $b) {
Expand Down
5 changes: 5 additions & 0 deletions src/models/generic/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ public function any(): bool
{
return $this->count() > 0;
}

public function updateCount(int $count)
{
$this->count = $count;
}
}
26 changes: 24 additions & 2 deletions src/prompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,29 @@
require_once './vendor/autoload.php';

use vending\ui\ConsoleUI;
use vending\models\Coins;
use vending\models\Coin;
use vending\models\Product;

$console = new ConsoleUI();
$console->setDefaultValues();
function defaultValues()
{
$coinManager = new vending\CoinManager(
new Coins(
new Coin(0.05, 10),
new Coin(0.1, 10),
new Coin(0.25, 10),
new Coin(1, 10)
)
);

$products = new vending\models\Products(
new Product('WATER', 0.65, 10),
new Product('JUICE', 1.00, 10),
new Product('SODA', 1.50, 10)
);

return new \vending\VendingMachine($coinManager, $products);
}

$console = new ConsoleUI(defaultValues());
$console->start();
91 changes: 91 additions & 0 deletions src/ui/BaseShell.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php declare(strict_types=1);

namespace vending\ui;

use vending\ui\BaseCommand;
use vending\ui\output\ConsoleOutput;

class BaseShell
{
protected $vendingMachine;
protected $consoleOutput;
protected $running = true;

public function __construct(\vending\VendingMachine $vendingMachine)
{
$this->consoleOutput = new ConsoleOutput();
$this->vendingMachine = $vendingMachine;
}

public function start()
{
$this->consoleOutput->writeln('');
$this->consoleOutput->writeln($this->header());

while ($this->running) {
// $this->consoleOutput->write();
$line = readline($this->prompt());
$commands = $this->parse($line);
$this->processCommands(...$commands);
}
}

public function prompt():string
{
return ">";
}

protected function parse($line): array
{
$sanitized = trim(str_replace(' ', ' ', $line));
$commands = [];
foreach (explode(',', $sanitized) as $part) {
$commands[] = trim(str_replace('-', ' ', $part));
}
return $commands;
}

protected function processCommands(...$commands)
{
foreach ($commands as $fullCommand) {
$args = explode(' ', $fullCommand);
$command = array_shift($args);

if (strtoupper($command) == 'EXIT') {
$this->running = false;
return;
}

if ($command) {
$command = ucfirst(strtolower($command));
if (is_numeric($command)) {
$args = [$command];
$command = 'AddCoin';
}
$this->execute($command, ...$args);
}
}
}

protected function execute($command, ...$args)
{
$commandInstance = $this->initializeCommand($command);
if ($commandInstance) {
$result = $commandInstance->execute(...$args);
if (!empty($result)) {
$this->consoleOutput->writeln(' -> ' . $result . PHP_EOL);
}
}
}


protected function initializeCommand(string $command)
{
try {
$class = new \ReflectionClass("vending\\ui\\commands\\{$command}Command");
return $class->newInstanceArgs([$this->vendingMachine, $this->consoleOutput]);
} catch (\ReflectionException $e) {
return false;
}
}
}
28 changes: 28 additions & 0 deletions src/ui/ConsoleUI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types=1);

namespace vending\ui;

use vending\ui\BaseCommand;
use vending\ui\output\ConsoleOutput;

final class ConsoleUI extends BaseShell
{
public function prompt():string
{
$insertedAmount = number_format($this->vendingMachine->getInsertedAmount(), 2, '.', ',');
return " $insertedAmount$ >";
}

public function header()
{
$productHeader = array_reduce(
$this->vendingMachine->getProducts()->toArray(),
function ($initial, $product) {
return $initial .= " ".$product->hash()."(".$product->count()."): ".(string)$product->getValue();
},
''
);

return ' PRODUCTS: '.$productHeader;
}
}
18 changes: 18 additions & 0 deletions src/ui/commands/AddCoinCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types=1);

namespace vending\ui\commands;

class AddCoinCommand extends BaseCommand
{
public function execute(...$args):string
{
if (count($args) > 0 && is_numeric($args[0])) {
$fvalue = $this->vendingMachine->insertCoin((float)$args[0]);
if ($fvalue != 0) {
return 'Invalid Coin to add! RETURN: '.$fvalue;
}
}
#we should throw error
return "";
}
}
Loading