<commit_before><?php
declare(strict_types=1);

namespace Piskvor;


/**
 * Class LifeBoard represents a board at a given generation. Note that we're internally representing species as ints, and only convert from/to strings on import/export.
 * @package Piskvor
 */
class LifeBoard
{
    /** @var bool true if all necessary parameters have been passed, false otherwise */
    private $initialized = false;
    /** @var int current generation. 0 for the initial import, incremented by 1 for every generation */
    private $generation;

    /** @var int number of cells per row and column (i.e. 10 means 10 rows x 10 cols = 100 cells */
    private $edgeSize;

    /** @var int number of species to inhabit the board @todo could be determined dynamically from data? */
    private $speciesCount;

    /** @var int maximum number of iterations to go through */
    private $maxIterations = 0;

    /** @var int[][] a matrix of organisms */
    private $organisms = array();

    /** @var int[] mapping string=>int of organism to internal rep */
    private $organismNameMap;
    /** @var string[] the inverse of $organismNameMap */
    private $organismNumberMap;

    /** @var bool if this becomes true, the pattern is static and won't ever change - do not recompute, just keep bumping generations */
    private $stillLife = false;

    /**
     * @return bool
     */
    public function isStillLife(): bool
    {
        return $this->stillLife;
    }

    /**
     * @param bool $isStillLife
     */
    public function setStillLife(bool $isStillLife)
    {
        $this->stillLife = $isStillLife;
    }

    public function __construct($organismNameMap = null, $generation = null)
    {
        $generation = (int)$generation;
        if (is_array($organismNameMap)) {
            $this->organismNameMap = $organismNameMap;
        } else {
            $this->organismNameMap = array();
        }
        if ($generation !== null) {
            $this->generation = $generation;
        } else {
            $this->generation = 0;
        }
    }

    /**
     * Return the ID of an organism on the given coords (0 for none)
     * @param int $x
     * @param int $y
     * @return int
     */
    public function getOrganism($x, $y): int
    {
        if (!isset($this->organisms[$x]) || !isset($this->organisms[$x][$y])) {
            return 0;
        } else {
            return $this->organisms[$x][$y];
        }
    }

    /**
     * Get all the organisms in a flat array
     * @return array
     */
    public function getAllOrganisms(): array
    {
        $results = array();
        foreach ($this->organisms as $x => $cols) {
            foreach ($cols as $y => $species) {
                $results[] = array(
                    'x' => $x,
                    'y' => $y,
                    'species' => $this->getOrganismNameByNumber($species)
                );
            }
        }
        return $results;
    }

    /**
     * Sets a cell with a given type of organism. If conflict, choose one.
     * @param int $x
     * @param int $y
     * @param int $organism
     * @return int the organism that's set
     */
    public function setOrganism($x, $y, $organism): int
    {
        if (!isset($this->organisms[$x])) {
            $this->organisms[$x] = array();
        }
        if (isset($this->organisms[$x][$y])) {
            // already occupied - find who survives
            $organism = $this->findSurvivor($this->organisms[$x][$y], $organism);
        }
        $this->organisms[$x][$y] = $organism;
        return $organism;
    }

    /**
     * Clears the cell unconditionally
     * @param $x
     * @param $y
     */
    public function clearOrganism($x, $y)
    {
        if (isset($this->organisms[$x], $this->organisms[$x][$y])) {
            unset($this->organisms[$x][$y]);
        }
    }

    /**
     * Clears the cell if occupied by this type of organism
     * @param int $x
     * @param int $y
     * @param int $organism
     */
    public function clearOrganismType($x, $y, $organism)
    {
        if (isset($this->organisms[$x], $this->organisms[$x][$y]) && $this->organisms[$x][$y] == $organism) {
            unset($this->organisms[$x][$y]);
        }
    }

    /**
     * @return int
     */
    public function getMaxIterations(): int
    {
        return $this->maxIterations;
    }

    /**
     * @param int $maxIterations
     * @return LifeBoard
     */
    public function setMaxIterations($maxIterations): LifeBoard
    {
        if ($maxIterations <= 0) {
            throw new \InvalidArgumentException('Iterations must be >0');
        }

        $this->maxIterations = $maxIterations;
        $this->initializeBoard();
        return $this;
    }

    /**
     * @return bool true if all necessary data has been set
     */
    public function isInitialized(): bool
    {
        return $this->initialized;
    }

    /**
     * @return LifeBoard
     */
    private function initializeBoard(): LifeBoard
    {
        $alreadyInitialized = $this->isInitialized();
        if (!$alreadyInitialized) {
            $this->initialized = ($this->getMaxIterations() > 0) && ($this->getEdgeSize() > 0) && ($this->getSpeciesCount() > 0);
            /*
             * @todo perhaps check if this would be faster than creating at access time?
             * @see $this->setOrganism()
            if ($this->initialized) {
                for ($x = $this->getEdgeSize() - 1; $x >= 0; $x--) {
                    $this->organisms[$x] = array();
                }
            }
            */<commit_msg>prevent nulls from being returned if checking for initialization<commit_after><?php
declare(strict_types=1);

namespace Piskvor;


/**
 * Class LifeBoard represents a board at a given generation. Note that we're internally representing species as ints, and only convert from/to strings on import/export.
 * @package Piskvor
 */
class LifeBoard
{
    /** @var bool true if all necessary parameters have been passed, false otherwise */
    private $initialized = false;
    /** @var int current generation. 0 for the initial import, incremented by 1 for every generation */
    private $generation;

    /** @var int number of cells per row and column (i.e. 10 means 10 rows x 10 cols = 100 cells */
    private $edgeSize;

    /** @var int number of species to inhabit the board @todo could be determined dynamically from data? */
    private $speciesCount;

    /** @var int maximum number of iterations to go through */
    private $maxIterations = 0;

    /** @var int[][] a matrix of organisms */
    private $organisms = array();

    /** @var int[] mapping string=>int of organism to internal rep */
    private $organismNameMap;
    /** @var string[] the inverse of $organismNameMap */
    private $organismNumberMap;

    /** @var bool if this becomes true, the pattern is static and won't ever change - do not recompute, just keep bumping generations */
    private $stillLife = false;

    /**
     * @return bool
     */
    public function isStillLife(): bool
    {
        return $this->stillLife;
    }

    /**
     * @param bool $isStillLife
     */
    public function setStillLife(bool $isStillLife)
    {
        $this->stillLife = $isStillLife;
    }

    public function __construct($organismNameMap = null, $generation = null)
    {
        $generation = (int)$generation;
        if (is_array($organismNameMap)) {
            $this->organismNameMap = $organismNameMap;
        } else {
            $this->organismNameMap = array();
        }
        if ($generation !== null) {
            $this->generation = $generation;
        } else {
            $this->generation = 0;
        }
    }

    /**
     * Return the ID of an organism on the given coords (0 for none)
     * @param int $x
     * @param int $y
     * @return int
     */
    public function getOrganism($x, $y): int
    {
        if (!isset($this->organisms[$x]) || !isset($this->organisms[$x][$y])) {
            return 0;
        } else {
            return $this->organisms[$x][$y];
        }
    }

    /**
     * Get all the organisms in a flat array
     * @return array
     */
    public function getAllOrganisms(): array
    {
        $results = array();
        foreach ($this->organisms as $x => $cols) {
            foreach ($cols as $y => $species) {
                $results[] = array(
                    'x' => $x,
                    'y' => $y,
                    'species' => $this->getOrganismNameByNumber($species)
                );
            }
        }
        return $results;
    }

    /**
     * Sets a cell with a given type of organism. If conflict, choose one.
     * @param int $x
     * @param int $y
     * @param int $organism
     * @return int the organism that's set
     */
    public function setOrganism($x, $y, $organism): int
    {
        if (!isset($this->organisms[$x])) {
            $this->organisms[$x] = array();
        }
        if (isset($this->organisms[$x][$y])) {
            // already occupied - find who survives
            $organism = $this->findSurvivor($this->organisms[$x][$y], $organism);
        }
        $this->organisms[$x][$y] = $organism;
        return $organism;
    }

    /**
     * Clears the cell unconditionally
     * @param $x
     * @param $y
     */
    public function clearOrganism($x, $y)
    {
        if (isset($this->organisms[$x], $this->organisms[$x][$y])) {
            unset($this->organisms[$x][$y]);
        }
    }

    /**
     * Clears the cell if occupied by this type of organism
     * @param int $x
     * @param int $y
     * @param int $organism
     */
    public function clearOrganismType($x, $y, $organism)
    {
        if (isset($this->organisms[$x], $this->organisms[$x][$y]) && $this->organisms[$x][$y] == $organism) {
            unset($this->organisms[$x][$y]);
        }
    }

    /**
     * @return int
     */
    public function getMaxIterations(): int
    {
        return $this->maxIterations;
    }

    /**
     * @param int $maxIterations
     * @return LifeBoard
     */
    public function setMaxIterations($maxIterations): LifeBoard
    {
        if ($maxIterations <= 0) {
            throw new \InvalidArgumentException('Iterations must be >0');
        }

        $this->maxIterations = $maxIterations;
        $this->initializeBoard();
        return $this;
    }

    /**
     * @return bool true if all necessary data has been set
     */
    public function isInitialized(): bool
    {
        return $this->initialized;
    }

    /**
     * @return LifeBoard
     */
    private function initializeBoard(): LifeBoard
    {
        $alreadyInitialized = $this->isInitialized();
        if (!$alreadyInitialized) {
            $this->initialized = ($this->maxIterations > 0) && ($this->edgeSize > 0) && ($this->speciesCount > 0);
            /*
             * @todo perhaps check if this would be faster than creating at access time?
             * @see $this->setOrganism()
            if ($this->initialized) {
                for ($x = $this->getEdgeSize() - 1; $x >= 0; $x--) {
                    $this->organisms[$x] = array();
                }
            }
            */
{'fraction_non_alphanumeric': 0.13677049767275332, 'fraction_numerical': 0.004117436448263516, 'mean_word_length': 1.9754993342210385, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 99, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5171087', 'n_tokens_mistral': 3326, 'n_tokens_neox': 3144, 'n_words': 938}