Permalink
Browse files

Merge pull request #7 from pepellou/master

The kata in PHP
  • Loading branch information...
2 parents 34ba1c2 + 515ac19 commit 729280b0078e5f7d81aec8a2d53d13197e8a1eac @12meses12katas committed Apr 9, 2012
Showing with 533 additions and 0 deletions.
  1. +9 −0 pepellou/php/phpunit.xml
  2. +200 −0 pepellou/php/src/Book.php
  3. +269 −0 pepellou/php/test/BookTest.php
  4. +55 −0 pepellou/php/test/PackTest.php
View
@@ -0,0 +1,9 @@
+<phpunit>
+ <testsuites>
+
+ <testsuite name="AllTests">
+ <directory>test</directory>
+ </testsuite>
+
+ </testsuites>
+</phpunit>
View
@@ -0,0 +1,200 @@
+<?php
+
+class NoSuchBook extends Exception {}
+
+class Book {
+
+ public static $FIRST = "Harry Potter and the Philosopher's Stone";
+ public static $SECOND = "Harry Potter and the Chamber of Secrets";
+ public static $THIRD = "Harry Potter and the Prisoner of Azkaban";
+ public static $FOURTH = "Harry Potter and the Goblet of Fire";
+ public static $FIFTH = "Harry Potter and the Order of the Phoenix";
+
+ private $name;
+
+ public function __construct(
+ $book_name
+ ) {
+ $this->name = $book_name;
+ if (!$this->exists())
+ throw new NoSuchBook;
+ }
+
+ private function exists(
+ ) {
+ $known_books = array(
+ self::$FIRST,
+ self::$SECOND,
+ self::$THIRD,
+ self::$FOURTH,
+ self::$FIFTH
+ );
+ return (in_array($this->name, $known_books));
+ }
+
+ public function price(
+ ) {
+ return 8;
+ }
+
+ public function __toString(
+ ) {
+ return $this->name;
+ }
+
+}
+
+class Pack {
+
+ private $books;
+ private $subpacks;
+
+ public function __construct(
+ ) {
+ $this->books = func_get_args();
+ $this->refreshSubpacks();
+ }
+
+ private function refreshSubpacks(
+ ) {
+ if (!$this->isAtomic())
+ $this->buildSubpacks();
+ }
+
+ public function addBook(
+ $book
+ ) {
+ $this->books []= $book;
+ }
+
+ public function contains(
+ $book
+ ) {
+ return (in_array($book, $this->books));
+ }
+
+ private function place_in_first_valid_subpack(
+ $book
+ ) {
+ $placed = false;
+ foreach ($this->subpacks as $subpack) {
+ if (!$placed) {
+ if (!$subpack->contains($book)) {
+ $subpack->addBook($book);
+ $placed = true;
+ }
+ }
+ }
+ return $placed;
+ }
+
+ private function getValueFor(
+ $book,
+ $subpack
+ ) {
+ if (!$subpack->contains($book)) {
+ $values = array(
+ 0 => 0,
+ 1 => 0.7,
+ 2 => 0.8,
+ 3 => 1,
+ 4 => 0.9,
+ 5 => 0.5
+ );
+ return $values[$subpack->numberOfDifferentBooks()];
+ }
+ return 0;
+ }
+
+ private function place_in_best_subpack(
+ $book
+ ) {
+ $placed = false;
+ $best_subpack = null;
+ $best_subpack_value = 0;
+ foreach ($this->subpacks as $subpack) {
+ if (!$placed) {
+ $new_heuristic = $this->getValueFor($book, $subpack);
+ if ($new_heuristic > $best_subpack_value) {
+ $best_subpack = $subpack;
+ $best_subpack_value = $new_heuristic;
+ }
+ }
+ }
+ if ($best_subpack != null) {
+ $best_subpack->addBook($book);
+ $placed = true;
+ }
+ return $placed;
+ }
+
+ public function buildSubpacks(
+ ) {
+ $this->subpacks = array();
+ foreach ($this->books as $book) {
+ $placed = $this->place_in_best_subpack($book);
+ if (!$placed) {
+ $this->subpacks []= new Pack($book);
+ }
+ }
+ }
+
+ public function price(
+ ) {
+ return ($this->isAtomic())
+ ? $this->getBooksPrice() * $this->getDiscount()
+ : $this->totalSumOfSubpacks();
+ }
+
+ public function totalSumOfSubpacks(
+ ) {
+ $total = 0;
+ foreach ($this->subpacks as $subpack) {
+ $total += $subpack->price();
+ }
+ return $total;
+ }
+
+ private function getBooksPrice(
+ ) {
+ $price = 0;
+ foreach ($this->books as $book) {
+ $price += $book->price();
+ }
+ return $price;
+ }
+
+ private function getDiscount(
+ ) {
+ $discounts = array(
+ 0 => 0,
+ 1 => 1,
+ 2 => 0.95,
+ 3 => 0.9,
+ 4 => 0.8,
+ 5 => 0.75
+ );
+ return $discounts[$this->numberOfDifferentBooks()];
+ }
+
+ private function numberOfDifferentBooks(
+ ) {
+ return count(array_unique($this->books));
+ }
+
+ public function numberOfBooks(
+ ) {
+ return count($this->books);
+ }
+
+ public function __toString(
+ ) {
+ return "Pack {" . implode(", ", $this->books) . "}";
+ }
+
+ public function isAtomic(
+ ) {
+ return ($this->numberOfBooks() == $this->numberOfDifferentBooks());
+ }
+
+}
Oops, something went wrong.

0 comments on commit 729280b

Please sign in to comment.