diff --git a/.idea/php-test-framework.xml b/.idea/php-test-framework.xml
new file mode 100644
index 0000000..e47438f
--- /dev/null
+++ b/.idea/php-test-framework.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
index f6159c8..f19075c 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -1,4 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Bread.php b/src/Bread.php
new file mode 100644
index 0000000..674db1e
--- /dev/null
+++ b/src/Bread.php
@@ -0,0 +1,8 @@
+priceListCollection = $priceListCollection;
+ }
+
+ public function priceFor(Good $good): Pound
{
- return new Pound(5);
+ return $this->priceListCollection->currentFor($good);
}
public function sellTo(Offer $offer): Pound
{
- return new Pound(
- $offer->amount()->amount() *
- $this->priceFor($offer->good())->amount()
- );
+ $cost = $this
+ ->priceFor($offer->good())
+ ->mult($offer->amount()->amount());
+
+ $this->priceListCollection->moveFor($offer->good(), -$offer->amount()->amount());
+
+ return $cost;
+ }
+
+ public function buyFrom(Offer $offer): Pound
+ {
+ $cost = $this
+ ->priceFor($offer->good())
+ ->mult($offer->amount()->amount());
+
+ $this->priceListCollection->moveFor($offer->good(), $offer->amount()->amount());
+
+ return $cost;
}
}
diff --git a/src/Milk.php b/src/Milk.php
index 8689abe..33e7410 100644
--- a/src/Milk.php
+++ b/src/Milk.php
@@ -3,8 +3,4 @@
final class Milk extends Good
{
- public function isMilk(): bool
- {
- return true;
- }
}
diff --git a/src/Pound.php b/src/Pound.php
index 1be124e..c1fe52e 100644
--- a/src/Pound.php
+++ b/src/Pound.php
@@ -17,4 +17,9 @@ public function amount(): int
{
return $this->amount;
}
+
+ public function mult(int $multiplier): Pound
+ {
+ return new Pound($this->amount * $multiplier);
+ }
}
diff --git a/src/PriceList.php b/src/PriceList.php
index 8a6a231..f98e330 100644
--- a/src/PriceList.php
+++ b/src/PriceList.php
@@ -30,4 +30,25 @@ public function current(): Pound
{
return $this->prices[$this->position];
}
+
+ public function move(int $positions): Pound
+ {
+ $nextPosition = $this->position + $positions;
+
+ if ($nextPosition >= count($this->prices)) {
+ $this->position = count($this->prices) - 1;
+
+ return $this->current();
+ }
+
+ if ($nextPosition < 0) {
+ $this->position = 0;
+
+ return $this->current();
+ }
+
+ $this->position = $nextPosition;
+
+ return $this->current();
+ }
}
diff --git a/src/PriceListBuilder.php b/src/PriceListBuilder.php
index bc0da06..1bf3efe 100644
--- a/src/PriceListBuilder.php
+++ b/src/PriceListBuilder.php
@@ -15,7 +15,87 @@ public function milkPrices(): PriceList
new Pound(7),
new Pound(7),
new Pound(8),
- new Pound(8)
+ new Pound(8),
);
}
+
+ public function woolPrices(): PriceList
+ {
+ return PriceList::fromList(
+ new Pound(3),
+ new Pound(3),
+ new Pound(4),
+ new Pound(4),
+ new Pound(5),
+ new Pound(5),
+ new Pound(6),
+ new Pound(6),
+ new Pound(7),
+ new Pound(8),
+ );
+ }
+
+ public function grainPrices(): PriceList
+ {
+ return PriceList::fromList(
+ new Pound(3),
+ new Pound(3),
+ new Pound(4),
+ new Pound(5),
+ new Pound(6),
+ new Pound(6),
+ new Pound(7),
+ new Pound(7),
+ new Pound(8),
+ new Pound(8),
+ );
+ }
+
+ public function breadPrices(): PriceList
+ {
+ return PriceList::fromList(
+ new Pound(7),
+ new Pound(8),
+ new Pound(9),
+ new Pound(10),
+ new Pound(11),
+ new Pound(11),
+ new Pound(12),
+ new Pound(13),
+ new Pound(14),
+ new Pound(15),
+ );
+ }
+
+ public function cheesePrices(): PriceList
+ {
+ return PriceList::fromList(
+ new Pound(7),
+ new Pound(8),
+ new Pound(9),
+ new Pound(10),
+ new Pound(11),
+ new Pound(12),
+ new Pound(13),
+ new Pound(14),
+ new Pound(14),
+ new Pound(15),
+ );
+ }
+
+ public function whiskyPrices(): PriceList
+ {
+ return PriceList::fromList(
+ new Pound(7),
+ new Pound(8),
+ new Pound(9),
+ new Pound(10),
+ new Pound(11),
+ new Pound(12),
+ new Pound(13),
+ new Pound(14),
+ new Pound(15),
+ new Pound(16),
+ );
+ }
}
diff --git a/src/PriceListCollection.php b/src/PriceListCollection.php
new file mode 100644
index 0000000..c4e0707
--- /dev/null
+++ b/src/PriceListCollection.php
@@ -0,0 +1,44 @@
+priceLists = [];
+ }
+
+ public function registerPriceListForGood(Good $good, PriceList $priceList): void
+ {
+ $this->priceLists[get_class($good)] = $priceList;
+ }
+
+ public function currentFor(Good $good): Pound
+ {
+ $this->ensureGoodHasPriceList($good);
+
+ return $this->priceLists[get_class($good)]->current();
+ }
+
+ public function moveFor(Good $good, int $positions): Pound
+ {
+ $this->ensureGoodHasPriceList($good);
+
+ return $this->priceLists[get_class($good)]->move($positions);
+ }
+
+ private function ensureGoodHasPriceList(Good $good): void
+ {
+ if (!isset($this->priceLists[get_class($good)])) {
+ throw new InvalidArgumentException(sprintf("Good: %s is unknown", get_class($good)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Whisky.php b/src/Whisky.php
new file mode 100644
index 0000000..fd67901
--- /dev/null
+++ b/src/Whisky.php
@@ -0,0 +1,8 @@
+ '/Pound.php',
'clansofcaledonia\\pricelist' => '/PriceList.php',
'clansofcaledonia\\pricelistbuilder' => '/PriceListBuilder.php',
- 'clansofcaledonia\\unit' => '/Unit.php'
+ 'clansofcaledonia\\unit' => '/Unit.php',
+ 'clansofcaledonia\\pricelistcollection' => '/PriceListCollection.php',
+ 'clansofcaledonia\\wool' => '/Wool.php'
);
}
$cn = strtolower($class);
diff --git a/tests/GoodTest.php b/tests/GoodTest.php
deleted file mode 100644
index f44ff47..0000000
--- a/tests/GoodTest.php
+++ /dev/null
@@ -1,18 +0,0 @@
-assertTrue($milk->isMilk());
- }
-}
diff --git a/tests/MarketTest.php b/tests/MarketTest.php
index d01128e..22605b3 100644
--- a/tests/MarketTest.php
+++ b/tests/MarketTest.php
@@ -10,24 +10,41 @@
* @uses \ClansOfCaledonia\Good
* @uses \ClansOfCaledonia\Offer
* @uses \ClansOfCaledonia\Unit
+ * @uses \ClansOfCaledonia\PriceList
+ * @uses \ClansOfCaledonia\PriceListCollection
+ * @uses \ClansOfCaledonia\PriceListBuilder
*/
final class MarketTest extends TestCase
{
public function testMilkCosts5PoundsInitially(): void
{
- $market = new Market;
+ $milk = new Milk();
+ $priceListBuilder = new PriceListBuilder();
+ $milkPrices = $priceListBuilder->milkPrices();
- $this->assertEquals(new Pound(5), $market->priceFor(Good::milk()));
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood($milk, $milkPrices);
+
+ $market = new Market($priceListCollection);
+
+ $this->assertEquals(new Pound(5), $market->priceFor($milk));
}
public function testMilkCanBeSoldToTheMarket(): Market
{
- $market = new Market;
+ $milk = new Milk();
+ $priceListBuilder = new PriceListBuilder();
+ $milkPrices = $priceListBuilder->milkPrices();
+
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood($milk, $milkPrices);
+
+ $market = new Market($priceListCollection);
$payment = $market->sellTo(
new Offer(
new Unit(2),
- Good::milk()
+ $milk
)
);
@@ -36,11 +53,45 @@ public function testMilkCanBeSoldToTheMarket(): Market
return $market;
}
- /**
- * @depends testMilkCanBeSoldToTheMarket
- */
- public function testSellingMilkToTheMarketReducesMilkPrice(Market $market): void
+ public function testSellingMilkToTheMarketReducesMilkPrice(): void
{
- $this->assertEquals(new Pound(4), $market->priceFor(Good::milk()));
+ $milk = new Milk();
+ $priceListBuilder = new PriceListBuilder();
+ $milkPrices = $priceListBuilder->milkPrices();
+
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood($milk, $milkPrices);
+
+ $market = new Market($priceListCollection);
+
+ $offer = new Offer(
+ new Unit(3),
+ $milk
+ );
+
+ $market->sellTo($offer);
+
+ $this->assertEquals(new Pound(3), $milkPrices->current());
+ }
+
+ public function testBuyingMilkFromTheMarketIncresesMilkPrice(): void
+ {
+ $milk = new Milk();
+ $priceListBuilder = new PriceListBuilder();
+ $milkPrices = $priceListBuilder->milkPrices();
+
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood($milk, $milkPrices);
+
+ $market = new Market($priceListCollection);
+
+ $offer = new Offer(
+ new Unit(3),
+ $milk
+ );
+
+ $market->buyFrom($offer);
+
+ $this->assertEquals(new Pound(7), $milkPrices->current());
}
}
diff --git a/tests/OfferTest.php b/tests/OfferTest.php
index 9c0e029..0810160 100644
--- a/tests/OfferTest.php
+++ b/tests/OfferTest.php
@@ -13,8 +13,15 @@ final class OfferTest extends TestCase
{
public function testHasAmount(): void
{
- $offer = new Offer(new Unit(1), Good::milk());
+ $offer = new Offer(new Unit(1), new Milk());
$this->assertEquals(new Unit(1), $offer->amount());
}
+
+ public function testHasGood(): void
+ {
+ $offer = new Offer(new Unit(1), new Milk());
+
+ $this->assertEquals(new Milk(), $offer->good());
+ }
}
diff --git a/tests/PoundTest.php b/tests/PoundTest.php
index 3d3ec6d..37b0425 100644
--- a/tests/PoundTest.php
+++ b/tests/PoundTest.php
@@ -16,4 +16,14 @@ public function testHasAmount(): void
$this->assertSame($amount, $p->amount());
}
+
+ public function testMultiply(): void
+ {
+ $amount = 100;
+
+ $p = new Pound($amount);
+ $newPound = $p->mult(5);
+
+ $this->assertSame(500, $newPound->amount());
+ }
}
diff --git a/tests/PriceListBuilderTest.php b/tests/PriceListBuilderTest.php
index 5df7e04..f69b689 100644
--- a/tests/PriceListBuilderTest.php
+++ b/tests/PriceListBuilderTest.php
@@ -19,4 +19,49 @@ public function testCanBuildMilkPriceList(): void
$this->assertEquals(new Pound(5), $milkPrices->current());
}
+
+ public function testCanBuildBreadPriceList(): void
+ {
+ $builder = new PriceListBuilder;
+
+ $breadPrices = $builder->breadPrices();
+
+ $this->assertEquals(new Pound(10), $breadPrices->current());
+ }
+
+ public function testCanBuildWoolPriceList(): void
+ {
+ $builder = new PriceListBuilder;
+
+ $woolPrices = $builder->woolPrices();
+
+ $this->assertEquals(new Pound(4), $woolPrices->current());
+ }
+
+ public function testCanBuildCheesePriceList(): void
+ {
+ $builder = new PriceListBuilder;
+
+ $cheesePrices = $builder->cheesePrices();
+
+ $this->assertEquals(new Pound(10), $cheesePrices->current());
+ }
+
+ public function testCanBuildWhiskyPriceList(): void
+ {
+ $builder = new PriceListBuilder;
+
+ $whiskyPrices = $builder->whiskyPrices();
+
+ $this->assertEquals(new Pound(10), $whiskyPrices->current());
+ }
+
+ public function testCanBuildGrainPriceList(): void
+ {
+ $builder = new PriceListBuilder;
+
+ $grainPrices = $builder->grainPrices();
+
+ $this->assertEquals(new Pound(5), $grainPrices->current());
+ }
}
diff --git a/tests/PriceListCollectionTest.php b/tests/PriceListCollectionTest.php
new file mode 100644
index 0000000..4de6a0f
--- /dev/null
+++ b/tests/PriceListCollectionTest.php
@@ -0,0 +1,55 @@
+milkPrices();
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood(new Milk(), $milkPriceList);
+
+ $this->assertEquals($milkPriceList->current(), $priceListCollection->currentFor($milk));
+ }
+
+ public function testMoveForGood(): void
+ {
+ $position = 3;
+ $milk = new Milk();
+ $priceListBuilder = new PriceListBuilder;
+ $milkPriceList = $priceListBuilder->milkPrices();
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood(new Milk(), $milkPriceList);
+ $priceListCollection->moveFor($milk, $position);
+
+ $this->assertEquals($milkPriceList->current(), $priceListCollection->currentFor($milk));
+ }
+
+ public function testUnregisteredGood(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+
+ $position = 3;
+ $wool = new Wool();
+ $priceListBuilder = new PriceListBuilder;
+ $milkPriceList = $priceListBuilder->milkPrices();
+ $priceListCollection = new PriceListCollection();
+ $priceListCollection->registerPriceListForGood(new Milk(), $milkPriceList);
+ $priceListCollection->moveFor($wool, $position);
+ }
+}
\ No newline at end of file
diff --git a/tests/PriceListTest.php b/tests/PriceListTest.php
index aba7abb..93f5141 100644
--- a/tests/PriceListTest.php
+++ b/tests/PriceListTest.php
@@ -27,4 +27,40 @@ public function testHasInitialPrice(): void
$this->assertEquals(new Pound(4), $prices->current());
}
+
+ public function dataProviderForMovePostionUp(): array
+ {
+ return [
+ [6, 2],
+ [4, 0],
+ [10, 6],
+ [10, 100],
+ [1, -100],
+ [2, -2],
+ [1, -4],
+ ];
+ }
+
+ /**
+ * @param int $expectedPound
+ * @param int $positionsToMove
+ * @dataProvider dataProviderForMovePostionUp
+ */
+ public function testMovePostionUp(int $expectedPound, int $positionsToMove): void
+ {
+ $prices = PriceList::fromList(
+ new Pound(1),
+ new Pound(2),
+ new Pound(3),
+ new Pound(4),
+ new Pound(5),
+ new Pound(6),
+ new Pound(7),
+ new Pound(8),
+ new Pound(9),
+ new Pound(10)
+ );
+
+ $this->assertEquals(new Pound($expectedPound), $prices->move($positionsToMove));
+ }
}