05-06-2015, 09:20 PM
Je me suis un peu planté pour l'or infini, voilà la correction.
<?php
interface GiveGoldByHero
{
public function giveGoldByHero(Gold $gold, Hero $hero);
}
interface Kid extends GiveGoldByHero { }
interface Women extends GiveGoldByHero
{
public function ageIsAskedByHero(Hero $hero);
}
interface WomenKid extends Women, Kid { }
interface Hero
{
public function askGoldByWomen(Women $women);
public function askGoldByKid(Kid $kid);
public function askGoldByWomenKid(WomenKid $womenKid);
public function ageOfWomenIs(Age $age);
}
final class Age
{
private $value;
public function __construct($value)
{
if (is_integer($value) === false) {
throw new RuntimeException('Age value should be construct from an integer');
}
if ($value < 0) {
throw new RuntimeException('Age value should be greater than or equal to 0');
}
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function executeIfGreaterOrEqualTo(callable $callable, self $age)
{
if ($this->value >= $age->value) {
$callable();
}
return $this;
}
}
final class Gold
{
private $value;
public function __construct($value)
{
if (is_integer($value) === false) {
throw new RuntimeException('Gold value should be construct from an integer');
}
if ($value < 0) {
throw new RuntimeException('Gold value should be greater than or equal to 0');
}
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
}
class Conan implements Hero
{
private $gold;
private $giveGold = false;
public function __construct(Gold $gold)
{
$this->gold = $gold->getValue();
}
public function askGoldByWomen(Women $women)
{
if ($this->gold < 2) {
return;
}
$hero = clone $this;
$women->ageIsAskedByHero($hero);
if ($hero->giveGold === true) {
$this->gold = $this->gold - 2;
$women->giveGoldByHero(new Gold(2), $hero);
echo "[Hero] I still have " . $this->gold . " gold\n";
}
}
public function askGoldByKid(Kid $kid)
{
if ($this->gold < 1) {
return;
}
$this->gold = $this->gold - 1;
$kid->giveGoldByHero(new Gold(1), $this);
echo "[Hero] I still have " . $this->gold . " gold\n";
}
public function askGoldByWomenKid(WomenKid $womenKid)
{
if ($this->gold === 0) {
return;
}
$hero = clone $this;
$womenKid->ageIsAskedByHero($hero);
if ($hero->giveGold === true) {
$gold = $this->gold;
$this->gold = 0;
$womenKid->giveGoldByHero(new Gold($gold), $hero);
echo "[Hero] I still have " . $this->gold . " gold\n";
}
}
public function ageOfWomenIs(Age $age)
{
$age->executeIfGreaterOrEqualTo(
function () { $this->giveGold = true; },
new Age(18)
);
}
}
class Gamin implements Kid
{
public function giveGoldByHero(Gold $gold, Hero $hero)
{
echo "Goood i can buy candies for " . $gold->getValue() . " gold\n";
}
}
class BBardot implements Women
{
private $age = 80;
public function giveGoldByHero(Gold $gold, Hero $hero)
{
echo "I can feed pet with food cost " . $gold->getValue() . " gold\n";
}
public function ageIsAskedByHero(Hero $hero)
{
$hero->ageOfWomenIs(new Age($this->age));
}
}
class Gamine implements WomenKid
{
private $age = 9;
public function giveGoldByHero(Gold $gold, Hero $hero)
{
echo "I can trick for " . $gold->getValue() . " gold\n";
}
public function ageIsAskedByHero(Hero $hero)
{
$hero->ageOfWomenIs(new Age($this->age * 10));
}
}
$conan = new Conan(new Gold(300));
$gamin = new Gamin;
$bbardot = new Bbardot;
$gamine = new Gamine;
$conan->askGoldByKid($gamin);
$conan->askGoldByWomen($bbardot);
$conan->askGoldByWomenKid($gamine);