123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- <?php
- namespace App\Yr\Forecast\Tabular\Variation;
- use App\Yr\Forecast\Tabular\Time;
- use App\Yr\Forecast\Tabular\Time\DiffInterface;
- if (!function_exists('array_key_last')) {
- function array_key_last(array $args): ?int {
- $keys = array_keys($args);
- return array_pop($keys);
- }
- }
- class VariationFn {
- private $fn, $v;
- public function __construct(callable $fn, Variation $v) {
- $this->fn = $fn;
- $this->v = $v;
- }
- public function callable(DiffInterface $e): ?bool {
- $callable = $this->fn;
- return $callable(
- $e,
- $this->v->getIntersect($e),
- $this->v->getIntersected($e)
- );
- }
- }
- class Variation implements \IteratorAggregate {
- private $time;
- private $entities = [];
- private $intersected = [];
- private $intersects = [];
- public function __construct(Time $t) {
- $this->time = $t;
- }
- public function addEntity(DiffInterface $entity, ?Variation $intersects): self {
- $this->entities[] = $entity;
- if ($intersects != null) {
- $this->intersects[array_key_last($this->entities)] = $intersects;
- $intersects->addIntersected($entity, $this);
- }
- return $this;
- }
- public function getTime(): Time {
- return $this->time;
- }
- private function getEntityKey(DiffInterface $entity): ?int {
- $key = (function() use ($entity) : ?int {
- foreach ($this->entities as $key => $ent)
- if ($ent instanceof $entity)
- return $key;
- return null;
- })();
- return $key;
- }
- public function getIntersect(DiffInterface $entity): ?Variation {
- $key = $this->getEntityKey($entity);
- if ($key === null || !isset($this->intersects[$key]))
- return null;
- return $this->intersects[$key];
- }
- public function getIntersected(DiffInterface $entity): ?Variation {
- $key = $this->getEntityKey($entity);
- if ($key === null || !isset($this->intersected[$key]))
- return null;
- foreach ($this->intersected[$key] as $var)
- if ($var->getEntity(get_class($entity)) != null)
- return $var;
- }
- protected function addIntersected(DiffInterface $entity, Variation $var): self {
- $key = $this->getEntityKey($entity);
- if ($key === null)
- return $this;
- if (!isset($this->intersected[$key]))
- $this->intersected[$key] = [$var];
- else
- $this->intersected[$key][] = $var;
- return $this;
- }
- public function isEmpty(): bool {
- return empty($this->entities);
- }
- public function filter(callable $filterFn): ?Variation {
- $entities = array_filter($this->entities, [
- new VariationFn($filterFn, $this), 'callable',
- ]);
- if (count($entities) == 0)
- return null;
- $var = new Variation($this->time);
- foreach ($entities as $entity)
- $var->addEntity($entity, $this->getIntersect($entity));
- return $var;
- }
- public function operate(callable $opFn): void {
- array_walk($this->entities, [
- new VariationFn($opFn, $this), 'callable'
- ]);
- }
- public function numEntities(): int {
- return sizeof($this->entities);
- }
- public function getEntity(string $class): ?DiffInterface {
- foreach ($this as $entity)
- if ($entity instanceof $class)
- return $entity;
- return null;
- }
- public function getIterator(): ?\Generator {
- foreach ($this->entities as $entity)
- yield $entity;
- return null;
- }
- }
|