0.0 .. 1.0 public function __construct( public readonly string $name, private readonly bool $introvert = true, ) {} public function sleep(int $hours): void { $this->sleepDebt = max(0, $this->sleepDebt + self::HOURS_NEEDED - $hours); $this->energy = min(self::MAX_ENERGY, $hours * 12 - $this->sleepDebt * 5); $this->stress *= 0.7; // sleep helps. a bit. } public function work(int $hours, int $meetings = 0): void { $this->drain($hours * 6 + $meetings * 8); $this->stress += $meetings * 0.15; $this->openLoops += intdiv($meetings, 2); // every other meeting = a new action item } public function socialise(Person $other, int $minutes): void { // introverts pay for it; extroverts get paid $this->introvert ? $this->drain(intdiv($minutes, 2)) : $this->energy = min(self::MAX_ENERGY, $this->energy + intdiv($minutes, 5)); $current = $this->closeness[$other->name] ?? 0.0; $this->closeness[$other->name] = min(1.0, $current + $minutes / 600); } public function promise(): void { $this->openLoops++; $this->stress += 0.1; } public function followThrough(): void { if ($this->openLoops === 0) { return; } $this->openLoops--; $this->stress = max(0.0, $this->stress - 0.2); } public function mood(): Mood { return match (true) { $this->energy < 20 => Mood::Tired, $this->stress > 1.0, $this->openLoops > 5 => Mood::Anxious, $this->energy > 70 && $this->stress < 0.3 => Mood::Content, default => Mood::Fine, }; } // the public interface public function howAreYou(): Mood { return Mood::Fine; } public function closestFriend(): ?string { if (!$this->closeness) { return null; } arsort($this->closeness); return array_key_first($this->closeness); } private function drain(int $amount): void { $this->energy = max(0, $this->energy - $amount); } } $me = new Person('pooper'); $me->sleep(hours: 5); $me->work(hours: 9, meetings: 6); echo $me->howAreYou()->value; // fine echo $me->mood()->value; // tired