continue phpcs fixes

This commit is contained in:
Dennis Eichhorn 2019-10-10 12:00:54 +02:00
parent 1ecf3e8d8c
commit 89c6ba3ac0
27 changed files with 1281 additions and 205 deletions

View File

@ -15,7 +15,7 @@ declare(strict_types=1);
namespace phpOMS\Algorithm\Knappsack; namespace phpOMS\Algorithm\Knappsack;
/** /**
* Matching a value with a set of coins * Item in the knappsack
* *
* @package phpOMS\Algorithm\Knappsack * @package phpOMS\Algorithm\Knappsack
* @license OMS License 1.0 * @license OMS License 1.0
@ -24,16 +24,56 @@ namespace phpOMS\Algorithm\Knappsack;
*/ */
class Item class Item
{ {
/**
* Value of the item
*
* @var float
* @since 1.0.0
*/
private $value = 0.0; private $value = 0.0;
/**
* Cost of the item
*
* @var float
* @since 1.0.0
*/
private $cost = 0.0; private $cost = 0.0;
public function getValue() /**
* Cosntructor.
*
* @param float $value Value of the item
* @param float $cost Cost of the item
*
* @since 1.0.0
*/
public function __construct(float $value, float $cost)
{
$this->value = $value;
$this->cost = $cost;
}
/**
* Get value of the item
*
* @return float
*
* @since 1.0.0
*/
public function getValue() : float
{ {
return $this->value; return $this->value;
} }
public function getCost() /**
* Get value of the item
*
* @return float
*
* @since 1.0.0
*/
public function getCost() : float
{ {
return $this->cost; return $this->cost;
} }

View File

@ -24,7 +24,7 @@ use phpOMS\Stdlib\Base\Heap;
* @link https://orange-management.org * @link https://orange-management.org
* @since 1.0.0 * @since 1.0.0
*/ */
class JumpPointSearch implements PathFinderInterface class AStar implements PathFinderInterface
{ {
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -48,9 +48,11 @@ class JumpPointSearch implements PathFinderInterface
$startNode->setF(0.0); $startNode->setF(0.0);
$startNode->setOpened(true); $startNode->setOpened(true);
$openList = new Heap(function(AStarNode $node1, AStarNode $node2) { return $node1->getF() - $node2->getF(); }); $openList = new Heap(function(AStarNode $node1, AStarNode $node2) {
$openList->push($startNode); return $node1->getF() - $node2->getF();
});
$openList->push($startNode);
$node = null; $node = null;
while (!$openList->isEmpty()) { while (!$openList->isEmpty()) {

View File

@ -24,69 +24,171 @@ namespace phpOMS\Algorithm\PathFinding;
*/ */
class AStarNode extends Node class AStarNode extends Node
{ {
/**
* The g score is cost of the path
*
* @var float
* @since 1.0.0
*/
private float $g = 0.0; private float $g = 0.0;
/**
* The heuristic distance is the cost to the end node
*
* @var float
* @since 1.0.0
*/
private ?float $h = null; private ?float $h = null;
/**
* The f score is defined as f(n) = g(n) + h(n)
*
* @var float
* @since 1.0.0
*/
private float $f = 0.0; private float $f = 0.0;
/**
* Define as checked node
*
* @var bool
* @since 1.0.0
*/
private bool $isClosed = false; private bool $isClosed = false;
private bool $isOpened = false;
private bool $isTested = false;
/**
* Define as potential candidate
*
* @var bool
* @since 1.0.0
*/
private bool $isOpened = false;
/**
* Is checked?
*
* @return bool
*
* @since 1.0.0
*/
public function isClosed() : bool public function isClosed() : bool
{ {
return $this->isClosed; return $this->isClosed;
} }
/**
* Is potential candidate
*
* @return bool
*
* @since 1.0.0
*/
public function isOpened() : bool public function isOpened() : bool
{ {
return $this->isOpened; return $this->isOpened;
} }
public function isTested() : bool /**
{ * Set check status
return $this->isTested; *
} * @param bool $isClosed Is closed
*
* @return void
*
* @since 1.0.0
*/
public function setClosed(bool $isClosed) : void public function setClosed(bool $isClosed) : void
{ {
$this->isClosed = $isClosed; $this->isClosed = $isClosed;
} }
/**
* Set potential candidate
*
* @param bool $isOpened Is potential candidate
*
* @return void
*
* @since 1.0.0
*/
public function setOpened(bool $isOpened) : void public function setOpened(bool $isOpened) : void
{ {
$this->isOpened = $isOpened; $this->isOpened = $isOpened;
} }
public function setTested(bool $isTested) : void /**
{ * Set the g score
$this->isTested = $isTested; *
} * @param float $g G score
*
* @return void
*
* @since 1.0.0
*/
public function setG(float $g) : void public function setG(float $g) : void
{ {
$this->g = $g; $this->g = $g;
} }
/**
* Set the heuristic distance
*
* @param float $h H distance
*
* @return void
*
* @since 1.0.0
*/
public function setH(?float $h) : void public function setH(?float $h) : void
{ {
$this->h = $h; $this->h = $h;
} }
/**
* Set the f score
*
* @param float $f F score
*
* @return void
*
* @since 1.0.0
*/
public function setF(float $f) : void public function setF(float $f) : void
{ {
$this->f = $f; $this->f = $f;
} }
/**
* Get the g score
*
* @return float
*
* @since 1.0.0
*/
public function getG() : float public function getG() : float
{ {
return $this->g; return $this->g;
} }
/**
* Get the heuristic distance
*
* @return float
*
* @since 1.0.0
*/
public function getH() : ?float public function getH() : ?float
{ {
return $this->h; return $this->h;
} }
/**
* Get the f score
*
* @return float
*
* @since 1.0.0
*/
public function getF() : float public function getF() : float
{ {
return $this->f; return $this->f;

View File

@ -24,8 +24,19 @@ namespace phpOMS\Algorithm\PathFinding;
*/ */
class Grid class Grid
{ {
/**
* Grid system containing all nodes
*
* @var array
* @since 1.0.0
*/
private array $nodes = [[]]; private array $nodes = [[]];
/**
* Create a grid from an array
*
* @param array $gridArray Grid defined in an array (0 = empty, 1 = start, 2 = end, 9 = not walkable)
*/
public static function createGridFromArray(array $gridArray, string $node) : self public static function createGridFromArray(array $gridArray, string $node) : self
{ {
$grid = new self(); $grid = new self();
@ -44,11 +55,32 @@ class Grid
return $grid; return $grid;
} }
/**
* Set node at position
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
* @param Node $node Node to set
*
* @return void
*
* @since 1.0.0
*/
public function setNode(int $x, int $y, Node $node) : void public function setNode(int $x, int $y, Node $node) : void
{ {
$this->nodes[$y][$x] = $node; $this->nodes[$y][$x] = $node;
} }
/**
* Get node at position
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
*
* @return null|Node
*
* @since 1.0.0
*/
public function getNode(int $x, int $y) : ?Node public function getNode(int $x, int $y) : ?Node
{ {
if (!isset($this->nodes[$y]) || !isset($this->nodes[$y][$x])) { if (!isset($this->nodes[$y]) || !isset($this->nodes[$y][$x])) {
@ -59,6 +91,16 @@ class Grid
return $this->nodes[$y][$x]; return $this->nodes[$y][$x];
} }
/**
* Is node walkable"
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
*
* @return bool
*
* @since 1.0.0
*/
public function isWalkable(int $x, int $y) : bool public function isWalkable(int $x, int $y) : bool
{ {
if (!isset($this->nodes[$y]) || !isset($this->nodes[$y][$x]) || !$this->nodes[$y][$x]->isWalkable()) { if (!isset($this->nodes[$y]) || !isset($this->nodes[$y][$x]) || !$this->nodes[$y][$x]->isWalkable()) {
@ -68,6 +110,16 @@ class Grid
return true; return true;
} }
/**
* Get neighbors of node
*
* @param Node $node Node to get neighbors from
* @param int $movement Allowed movements
*
* @return array
*
* @since 1.0.0
*/
public function getNeighbors(Node $node, int $movement) : array public function getNeighbors(Node $node, int $movement) : array
{ {
$x = $node->getX(); $x = $node->getX();
@ -87,22 +139,22 @@ class Grid
// todo: check $x and $y because original implementation is flipped!!! // todo: check $x and $y because original implementation is flipped!!!
if ($this->isWalkable($x, $y - 1)) { if ($this->isWalkable($x, $y - 1)) {
$neighbors[] = $this->getNode($x, $y - 1); $neighbors[] = $this->getNode($x, $y - 1);
$s0 = true; $s0 = true;
} }
if ($this->isWalkable($x + 1, $y)) { if ($this->isWalkable($x + 1, $y)) {
$neighbors[] = $this->getNode($x + 1, $y); $neighbors[] = $this->getNode($x + 1, $y);
$s1 = true; $s1 = true;
} }
if ($this->isWalkable($x, $y + 1)) { if ($this->isWalkable($x, $y + 1)) {
$neighbors[] = $this->getNode($x, $y + 1); $neighbors[] = $this->getNode($x, $y + 1);
$s2 = true; $s2 = true;
} }
if ($this->isWalkable($x - 1, $y)) { if ($this->isWalkable($x - 1, $y)) {
$neighbors[] = $this->getNode($x - 1, $y); $neighbors[] = $this->getNode($x - 1, $y);
$s3 = true; $s3 = true;
} }
if ($movement === MovementType::STRAIGHT) { if ($movement === MovementType::STRAIGHT) {

View File

@ -24,69 +24,205 @@ namespace phpOMS\Algorithm\PathFinding;
*/ */
class JumpPointNode extends Node class JumpPointNode extends Node
{ {
/**
* The g score is cost of the path
*
* @var float
* @since 1.0.0
*/
private float $g = 0.0; private float $g = 0.0;
/**
* The heuristic distance is the cost to the end node
*
* @var float
* @since 1.0.0
*/
private ?float $h = null; private ?float $h = null;
/**
* The f score is defined as f(n) = g(n) + h(n)
*
* @var float
* @since 1.0.0
*/
private float $f = 0.0; private float $f = 0.0;
/**
* Define as checked node
*
* @var bool
* @since 1.0.0
*/
private bool $isClosed = false; private bool $isClosed = false;
/**
* Define as potential candidate
*
* @var bool
* @since 1.0.0
*/
private bool $isOpened = false; private bool $isOpened = false;
/**
* The node was already tested?
*
* @var bool
* @since 1.0.0
*/
private bool $isTested = false; private bool $isTested = false;
/**
* Is checked?
*
* @return bool
*
* @since 1.0.0
*/
public function isClosed() : bool public function isClosed() : bool
{ {
return $this->isClosed; return $this->isClosed;
} }
/**
* Is potential candidate
*
* @return bool
*
* @since 1.0.0
*/
public function isOpened() : bool public function isOpened() : bool
{ {
return $this->isOpened; return $this->isOpened;
} }
/**
* Is already tested
*
* @return bool
*
* @since 1.0.0
*/
public function isTested() : bool public function isTested() : bool
{ {
return $this->isTested; return $this->isTested;
} }
/**
* Set check status
*
* @param bool $isClosed Is closed
*
* @return void
*
* @since 1.0.0
*/
public function setClosed(bool $isClosed) : void public function setClosed(bool $isClosed) : void
{ {
$this->isClosed = $isClosed; $this->isClosed = $isClosed;
} }
/**
* Set potential candidate
*
* @param bool $isOpened Is potential candidate
*
* @return void
*
* @since 1.0.0
*/
public function setOpened(bool $isOpened) : void public function setOpened(bool $isOpened) : void
{ {
$this->isOpened = $isOpened; $this->isOpened = $isOpened;
} }
/**
* Set tested
*
* @param bool $isTested Node tested?
*
* @return void
*
* @since 1.0.0
*/
public function setTested(bool $isTested) : void public function setTested(bool $isTested) : void
{ {
$this->isTested = $isTested; $this->isTested = $isTested;
} }
/**
* Set the g score
*
* @param float $g G score
*
* @return void
*
* @since 1.0.0
*/
public function setG(float $g) : void public function setG(float $g) : void
{ {
$this->g = $g; $this->g = $g;
} }
/**
* Set the heuristic distance
*
* @param float $h H distance
*
* @return void
*
* @since 1.0.0
*/
public function setH(?float $h) : void public function setH(?float $h) : void
{ {
$this->h = $h; $this->h = $h;
} }
/**
* Set the f score
*
* @param float $f F score
*
* @return void
*
* @since 1.0.0
*/
public function setF(float $f) : void public function setF(float $f) : void
{ {
$this->f = $f; $this->f = $f;
} }
/**
* Get the g score
*
* @return float
*
* @since 1.0.0
*/
public function getG() : float public function getG() : float
{ {
return $this->g; return $this->g;
} }
/**
* Get the heuristic distance
*
* @return float
*
* @since 1.0.0
*/
public function getH() : ?float public function getH() : ?float
{ {
return $this->h; return $this->h;
} }
/**
* Get the f score
*
* @return float
*
* @since 1.0.0
*/
public function getF() : float public function getF() : float
{ {
return $this->f; return $this->f;

View File

@ -48,7 +48,10 @@ class JumpPointSearch implements PathFinderInterface
$startNode->setF(0.0); $startNode->setF(0.0);
$startNode->setOpened(true); $startNode->setOpened(true);
$openList = new Heap(function($node1, $node2) { return $node1->getF() - $node2->getF(); }); $openList = new Heap(function($node1, $node2) {
return $node1->getF() - $node2->getF();
});
$openList->push($startNode); $openList->push($startNode);
$node = null; $node = null;
@ -73,6 +76,20 @@ class JumpPointSearch implements PathFinderInterface
return $path; return $path;
} }
/**
* Find possible successor jump points
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
* @param int $heuristic Heuristic/metrics type for the distance calculation
* @param int $movement Movement type
* @param JumpPointNode $endNode End node to find path to
* @param Heap $openList Heap of open nodes
*
* @return Heap
*
* @since 1.0.0
*/
public static function identifySuccessors(JumpPointNode $node, Grid $grid, int $heuristic, int $movement, JumpPointNode $endNode, Heap $openList) : Heap public static function identifySuccessors(JumpPointNode $node, Grid $grid, int $heuristic, int $movement, JumpPointNode $endNode, Heap $openList) : Heap
{ {
$neighbors = self::findNeighbors($node, $movement, $grid); $neighbors = self::findNeighbors($node, $movement, $grid);
@ -107,6 +124,17 @@ class JumpPointSearch implements PathFinderInterface
return $openList; return $openList;
} }
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param int $movement Movement type
* @param Grid $grid Grid of the nodes
*
* @return array Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighbors(JumpPointNode $node, int $movement, Grid $grid) : array private static function findNeighbors(JumpPointNode $node, int $movement, Grid $grid) : array
{ {
if ($movement === MovementType::STRAIGHT) { if ($movement === MovementType::STRAIGHT) {
@ -120,6 +148,16 @@ class JumpPointSearch implements PathFinderInterface
return self::findNeighborsDiagonalNoObstacle($node, $grid); return self::findNeighborsDiagonalNoObstacle($node, $grid);
} }
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return array Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsStraight(JumpPointNode $node, Grid $grid) : array private static function findNeighborsStraight(JumpPointNode $node, Grid $grid) : array
{ {
if ($node->getParent() === null) { if ($node->getParent() === null) {
@ -167,6 +205,16 @@ class JumpPointSearch implements PathFinderInterface
return $neighbors; return $neighbors;
} }
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return array Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonal(JumpPointNode $node, Grid $grid) : array private static function findNeighborsDiagonal(JumpPointNode $node, Grid $grid) : array
{ {
if ($node->getParent() === null) { if ($node->getParent() === null) {
@ -234,6 +282,16 @@ class JumpPointSearch implements PathFinderInterface
return $neighbors; return $neighbors;
} }
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return array Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonalOneObstacle(JumpPointNode $node, Grid $grid) : array private static function findNeighborsDiagonalOneObstacle(JumpPointNode $node, Grid $grid) : array
{ {
if ($node->getParent() === null) { if ($node->getParent() === null) {
@ -297,6 +355,16 @@ class JumpPointSearch implements PathFinderInterface
return $neighbors; return $neighbors;
} }
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return array Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonalNoObstacle(JumpPointNode $node, Grid $grid) : array private static function findNeighborsDiagonalNoObstacle(JumpPointNode $node, Grid $grid) : array
{ {
if ($node->getParent() === null) { if ($node->getParent() === null) {
@ -378,6 +446,18 @@ class JumpPointSearch implements PathFinderInterface
return $neighbors; return $neighbors;
} }
/**
* Find next jump point
*
* @param JumpPointNode $node Node to find jump point from
* @param JumpPointNode $endNode End node to find path to
* @param int $movement Movement type
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jump(JumpPointNode $node, JumpPointNode $endNode, int $movement, Grid $grid) : ?JumpPointNode private static function jump(JumpPointNode $node, JumpPointNode $endNode, int $movement, Grid $grid) : ?JumpPointNode
{ {
if ($movement === MovementType::STRAIGHT) { if ($movement === MovementType::STRAIGHT) {
@ -391,6 +471,17 @@ class JumpPointSearch implements PathFinderInterface
return self::jumpDiagonalNoObstacle($node, $endNode, $grid); return self::jumpDiagonalNoObstacle($node, $endNode, $grid);
} }
/**
* Find next jump point
*
* @param JumpPointNode $node Node to find jump point from
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpStraight(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode private static function jumpStraight(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{ {
$x = $node->getX(); $x = $node->getX();
@ -435,6 +526,17 @@ class JumpPointSearch implements PathFinderInterface
return self::jumpStraight($grid->getNode($x + $dx, $y + $dy), $node, $grid); return self::jumpStraight($grid->getNode($x + $dx, $y + $dy), $node, $grid);
} }
/**
* Find next jump point
*
* @param JumpPointNode $node Node to find jump point from
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonal(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode private static function jumpDiagonal(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{ {
$x = $node->getX(); $x = $node->getX();
@ -483,6 +585,17 @@ class JumpPointSearch implements PathFinderInterface
return self::jumpDiagonal($grid->getNode($x + $dx, $y + $dy), $node, $grid); return self::jumpDiagonal($grid->getNode($x + $dx, $y + $dy), $node, $grid);
} }
/**
* Find next jump point
*
* @param JumpPointNode $node Node to find jump point from
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonalOneObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode private static function jumpDiagonalOneObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{ {
$x = $node->getX(); $x = $node->getX();
@ -535,6 +648,17 @@ class JumpPointSearch implements PathFinderInterface
return null; return null;
} }
/**
* Find next jump point
*
* @param JumpPointNode $node Node to find jump point from
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonalNoObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode private static function jumpDiagonalNoObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{ {
$x = $node->getX(); $x = $node->getX();

View File

@ -24,21 +24,74 @@ namespace phpOMS\Algorithm\PathFinding;
*/ */
class Path class Path
{ {
/**
* Nodes in the path
*
* @var Nodes[]
* @since 1.0.0
*/
public array $nodes = []; public array $nodes = [];
/**
* Weight/cost of the total path
*
* @var float
* @since 1.0.0
*/
private float $weight = 0.0; private float $weight = 0.0;
/**
* Distance of the total path
*
* @var float
* @since 1.0.0
*/
private float $distance = 0.0; private float $distance = 0.0;
/**
* Grid this path belongs to
*
* @var Grid
* @since 1.0.0
*/
private Grid $grid; private Grid $grid;
/**
* Cosntructor.
*
* @param Grid $grid Grid this path belongs to
*
* @since 1.0.0
*/
public function __construct(Grid $grid) public function __construct(Grid $grid)
{ {
$this->grid = $grid; $this->grid = $grid;
} }
/**
* Add node to the path
*
* @param Node $node Node
*
* @return void
*
* @since 1.0.0
*/
public function addNode(Node $node) : void public function addNode(Node $node) : void
{ {
$this->nodes[] = $node; $this->nodes[] = $node;
} }
/**
* Fill all nodes in bettween
*
* The path may only contain the jump points or pivot points.
* In order to get every node it needs to be expanded.
*
* @return array
*
* @since 1.0.0
*/
public function expandPath() : array public function expandPath() : array
{ {
$reverse = \array_reverse($this->nodes); $reverse = \array_reverse($this->nodes);
@ -64,6 +117,19 @@ class Path
return $expanded; return $expanded;
} }
/**
* Find nodes in bettween two nodes.
*
* The path may only contain the jump points or pivot points.
* In order to get every node it needs to be expanded.
*
* @param Node $node1 Node
* @param Node $node2 Node
*
* @return array
*
* @since 1.0.0
*/
private function interpolate(Node $node1, Node $node2) : array private function interpolate(Node $node1, Node $node2) : array
{ {
$dx = \abs($node2->getX() - $node1->getX()); $dx = \abs($node2->getX() - $node1->getX());
@ -88,13 +154,13 @@ class Path
if ($e2 > -$dy) { if ($e2 > -$dy) {
$err -= $dy; $err -= $dy;
$x0 = $node->getX() + $sx; $x0 = $node->getX() + $sx;
} }
$y0 = 0; $y0 = 0;
if ($e2 < $dx) { if ($e2 < $dx) {
$err += $dx; $err += $dx;
$y0 = $node->getY() + $sy; $y0 = $node->getY() + $sy;
} }
$node = $this->grid->getNode($x0, $y0); $node = $this->grid->getNode($x0, $y0);

View File

@ -22,7 +22,8 @@ namespace phpOMS\Algorithm\PathFinding;
* @link https://orange-management.org * @link https://orange-management.org
* @since 1.0.0 * @since 1.0.0
*/ */
interface PathFinderInterface { interface PathFinderInterface
{
/** /**
* Find path from one point to another * Find path from one point to another
* *

View File

@ -14,6 +14,8 @@ declare(strict_types=1);
namespace phpOMS\Algorithm\Sort; namespace phpOMS\Algorithm\Sort;
use phpOMS\Utils\NumericUtils;
/** /**
* FlashSort class. * FlashSort class.
* *
@ -51,32 +53,32 @@ class FlashSort implements SortInterface
// todo: replace >>> with Numeric::uRightShift // todo: replace >>> with Numeric::uRightShift
for ($i = 0; (($i += 2) - $n) >>> 31;) { for ($i = 0; NumericUtils::uRightShift(($i += 2) - $n, 31);) {
if ((($kmax = $list[$i - 1])->getValue() - ($kmin = $list[$i])->getValue()) >>> 31) { if (NumericUtils::uRightShift(($kmax = $list[$i - 1])->getValue() - ($kmin = $list[$i])->getValue(), 31)) {
if (($kmax->getValue() - $anmin->getValue()) >>> 31) { if (NumericUtils::uRightShift($kmax->getValue() - $anmin->getValue(), 31)) {
$anmin = $list[$i - 1]; $anmin = $list[$i - 1];
} }
if (($anmax->getValue() - $kmin->getValue()) >>> 31) { if (NumericUtils::uRightShift($anmax->getValue() - $kmin->getValue(), 31)) {
$anmax = $list[$i]; $anmax = $list[$i];
$nmax = $i; $nmax = $i;
} }
} else { } else {
if (($kmin->getValue() - $anmin->getValue()) >>> 31) { if (NumericUtils::uRightShift($kmin->getValue() - $anmin->getValue(), 31)) {
$anmin = $list[$i]; $anmin = $list[$i];
} }
if (($anmax->getValue() - $kmin->getValue()) >>> 31) { if (NumericUtils::uRightShift($anmax->getValue() - $kmin->getValue(), 31)) {
$anmax = $list[$i - 1]; $anmax = $list[$i - 1];
$nmax = $i - 1; $nmax = $i - 1;
} }
} }
} }
if ((--$i - $n) >>> 31) { if (NumericUtils::uRightShift(--$i - $n, 31)) {
if ((($k = $list[$i])->getValue() - $anmin->getValue()) >>> 31) { if (NumericUtils::uRightShift(($k = $list[$i])->getValue() - $anmin->getValue(), 31)) {
$anmin = $list[$i]; $anmin = $list[$i];
} elseif (($anmax->getValue() - $k->getValue()) >>> 31) { } elseif (NumericUtils::uRightShift($anmax->getValue() - $k->getValue(), 31)) {
$anmax = $list[$i]; $anmax = $list[$i];
$nmax = $i; $nmax = $i;
} }
@ -88,12 +90,12 @@ class FlashSort implements SortInterface
$c1 = (($m - 1) << 13) / ($anmax->getValue() - $anmin->getValue()); $c1 = (($m - 1) << 13) / ($anmax->getValue() - $anmin->getValue());
for ($i = -1; (++$i - $n) >>> 31;) { for ($i = -1; NumericUtils::uRightShift(++$i - $n, 31);) {
++$l[($c1 * ($list[$i]->getValue() - $anmin->getValue())) >> 13]; ++$l[($c1 * ($list[$i]->getValue() - $anmin->getValue())) >> 13];
} }
$lk = $l[0]; $lk = $l[0];
for ($k = 0; (++$k - $m) >>> 31;) { for ($k = 0; NumericUtils::uRightShift(++$k - $m, 31);) {
$lk = ($l[$k] += $lk); $lk = ($l[$k] += $lk);
} }
@ -106,7 +108,7 @@ class FlashSort implements SortInterface
$k = ($m - 1); $k = ($m - 1);
$i = ($n - 1); $i = ($n - 1);
while (($nmove - $i) >>> 31) { while (NumericUtils::uRightShift($nmove - $i, 31)) {
while ($j !== $lk) { while ($j !== $lk) {
$k = ($c1 * ($list[(++$j)]->getValue() - $anmin->getValue())) >> 13; $k = ($c1 * ($list[(++$j)]->getValue() - $anmin->getValue())) >> 13;
} }
@ -114,7 +116,9 @@ class FlashSort implements SortInterface
$flash = $a[$j]; $flash = $a[$j];
$lk = $l[$k]; $lk = $l[$k];
while ($j !== $lk) while ($j !== $lk) {
}
} }
} }
} }

View File

@ -0,0 +1,27 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package phpOMS\DataStorage\Database\Query
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace phpOMS\DataStorage\Database\Query;
/**
* Database query builder.
*
* @package phpOMS\DataStorage\Database\Query
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
class Count extends Builder
{
}

View File

@ -265,4 +265,34 @@ final class Polygon implements D2ShapeInterface
return $barycenter; return $barycenter;
} }
/**
* Get area by side length
*
* @param float $length Side length
* @param int $sides Number of sides
*
* @return float
*
* @since 1.0.0
*/
public static function getRegularAreaByLength(float $length, int $sides) : float
{
return $length ** 2 * $sides / (4 * \tan(180 / $sides));
}
/**
* Get area by radius
*
* @param float $r Radius
* @param int $sides Number of sides
*
* @return float
*
* @since 1.0.0
*/
public static function getRegularAreaByRadius(float $r, int $sides) : float
{
return $r ** 2 * $sides * \sin(360 / $sides) / 2;
}
} }

View File

@ -13,7 +13,32 @@
declare(strict_types=1); declare(strict_types=1);
namespace phpOMS\Math\Geometry\Shape\D2; namespace phpOMS\Math\Geometry\Shape\D2;
/**
* Quadrilateral shape.
*
* @package phpOMS\Math\Geometry\Shape\D2
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
final class Quadrilateral implements D2ShapeInterface final class Quadrilateral implements D2ShapeInterface
{ {
/**
* Calculate the surface area from the length of all sides and the angle between a and b
*
* @param float $a Side a length
* @param float $b Side b length
* @param float $c Side c length
* @param float $d Side d length
* @param float $alpha Angle between side a and b
*
* @return float
*
* @since 1.0.0
*/
public static function getSurfaceFromSidesAndAngle(float $a, float $b, float $c, float $d, float $alpha) : float
{
return 1 / 2 * $a * $b * \sin($alpha) + 1 / 4
* \sqrt(4 * $c ** 2 * $d ** 2 - ($c ** 2 + $d ** 2 - $a ** 2 - $b ** 2 + 2 * $a * $b * \cos($alpha)) ** 2);
}
} }

View File

@ -4,7 +4,7 @@
* *
* PHP Version 7.4 * PHP Version 7.4
* *
* @package TBD * @package phpOMS\Math\Geometry\Shape\D3
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 1.0
* @version 1.0.0 * @version 1.0.0
@ -13,7 +13,61 @@
declare(strict_types=1); declare(strict_types=1);
namespace phpOMS\Math\Geometry\Shape\D3; namespace phpOMS\Math\Geometry\Shape\D3;
/**
* Prism shape.
*
* @package phpOMS\Math\Geometry\Shape\D3
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
final class Prism implements D3ShapeInterface final class Prism implements D3ShapeInterface
{ {
/**
* Get volume of regular polygon prism by side length
*
* @param float $length Side length
* @param int $sides Number of sides
* @param float $h Height
*
* @return float
*
* @since 1.0.0
*/
public static function getVolumeRegularLength(float $length, int $sides, float $h) : float
{
return Polygon::getRegularAreaByLength($length, $sides) * $h;
}
/**
* Get volume area of regular polygon prism by radius
*
* @param float $r Radius
* @param int $sides Number of sides
* @param float $h Height
*
* @return float
*
* @since 1.0.0
*/
public static function getVolumeRegularRadius(float $r, int $sides, float $h) : float
{
return Polygon::getRegularAreaByRadius($r, $sides) * $h;
}
/**
* Get surface area of regular polygon prism by side length
*
* @param float $length Side length
* @param int $sides Number of sides
* @param float $h Height
*
* @return float
*
* @since 1.0.0
*/
public static function getSurfaceRegularLength(float $length, int $sides, float $h) : float
{
return Polygon::getRegularAreaByLength($length, $sides) * 2 + $length * $sides * $h;
}
} }

View File

@ -1,20 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package TBD
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace phpOMS\Math\Integral;
class Gauss
{
}

View File

@ -859,11 +859,25 @@ final class EigenvalueDecomposition
} }
} }
/**
* Is matrix symmetric?
*
* @return bool
*
* @since 1.0.0
*/
public function isSymmetric() : bool public function isSymmetric() : bool
{ {
return $this->isSymmetric; return $this->isSymmetric;
} }
/**
* Get V matrix
*
* @return Matrix
*
* @since 1.0.0
*/
public function getV() : Matrix public function getV() : Matrix
{ {
$matrix = new Matrix(); $matrix = new Matrix();
@ -872,6 +886,13 @@ final class EigenvalueDecomposition
return $matrix; return $matrix;
} }
/**
* Get real eigenvalues
*
* @return Vector
*
* @since 1.0.0
*/
public function getRealEigenvalues() : Vector public function getRealEigenvalues() : Vector
{ {
$vector = new Vector(); $vector = new Vector();
@ -880,6 +901,13 @@ final class EigenvalueDecomposition
return $vector; return $vector;
} }
/**
* Get imaginary eigenvalues
*
* @return Vector
*
* @since 1.0.0
*/
public function getImagEigenvalues() : Vector public function getImagEigenvalues() : Vector
{ {
$vector = new Vector(); $vector = new Vector();
@ -888,6 +916,13 @@ final class EigenvalueDecomposition
return $vector; return $vector;
} }
/**
* Get D matrix
*
* @return Matrix
*
* @since 1.0.0
*/
public function getD() : Matrix public function getD() : Matrix
{ {
$matrix = new Matrix(); $matrix = new Matrix();

View File

@ -24,27 +24,52 @@ namespace phpOMS\Stdlib\Base;
*/ */
class Heap class Heap
{ {
/**
* Comparison function
*
* @var \Closure
* @since 1.0.0
*/
private \Closure $compare; private \Closure $compare;
/** /**
* Heap elements * Heap items
* *
* @var array<int, mixed> * @var array<int, mixed>
* @since 1.0.0 * @since 1.0.0
*/ */
private array $nodes = []; private array $nodes = [];
/**
* Constructor.
*
* @param null|\Closure $compare Compare function
*
* @since 1.0.0
*/
public function __construct(\Closure $compare = null) public function __construct(\Closure $compare = null)
{ {
$this->compare = $compare ?? function($a, $b) { return $a <=> $b; }; $this->compare = $compare ?? function($a, $b) {
return $a <=> $b;
};
} }
public function insort($x, $lo = 0) : void /**
* Insert item into sorted heap at correct position
*
* @param mixed $x Element to insert
* @param int $lo Lower bound
*
* @return void
*
* @since 1.0.0
*/
public function insort($x, int $lo = 0) : void
{ {
$hi = \count($this->nodes); $hi = \count($this->nodes);
while ($lo < $hi) { while ($lo < $hi) {
$mid = (int) \floor(($lo + $hi) / 2); $mid = (int) (($lo + $hi) / 2);
if (($this->compare)($x, $this->nodes[$mid]) < 0) { if (($this->compare)($x, $this->nodes[$mid]) < 0) {
$hi = $mid; $hi = $mid;
} else { } else {
@ -55,12 +80,28 @@ class Heap
$this->nodes = \array_splice($this->nodes, $lo, 0, $x); $this->nodes = \array_splice($this->nodes, $lo, 0, $x);
} }
/**
* Push item onto the heap
*
* @param mixed $item Item to add to the heap
*
* @return void;
*
* @since 1.0.0
*/
public function push($item) : void public function push($item) : void
{ {
$this->nodes[] = $item; $this->nodes[] = $item;
$this->siftDown(0, \count($this->nodes) - 1); $this->siftDown(0, \count($this->nodes) - 1);
} }
/**
* Pop the smallest item off the heap
*
* @return mixed
*
* @since 1.0.0
*/
public function pop() public function pop()
{ {
$last = \array_pop($this->nodes); $last = \array_pop($this->nodes);
@ -68,18 +109,34 @@ class Heap
return $last; return $last;
} }
$item = $this->nodes[0]; $item = $this->nodes[0];
$this->nodes[0] = $last; $this->nodes[0] = $last;
$this->siftUp(0); $this->siftUp(0);
return $item; return $item;
} }
/**
* Get first item without popping
*
* @return mixed
*
* @since 1.0.0
*/
public function peek() public function peek()
{ {
return $this->nodes[0]; return $this->nodes[0];
} }
/**
* Contains item?
*
* @param mixed $item Item to check
*
* @return bool
*
* @since 1.0.0
*/
public function contains($item) : bool public function contains($item) : bool
{ {
foreach ($this->nodes as $key => $node) { foreach ($this->nodes as $key => $node) {
@ -97,20 +154,38 @@ class Heap
return false; return false;
} }
/**
* Pop a item and push a new one (replace with a new one)
*
* @param mixed $new New item
*
* @return mixed popped item
*
* @since 1.0.0
*/
public function replace($new) public function replace($new)
{ {
$old = $this->nodes[0]; $old = $this->nodes[0];
$this->nodes[0] = $new; $this->nodes[0] = $new;
$this->siftUp(0); $this->siftUp(0);
return $old; return $old;
} }
/**
* Push item and pop one
*
* @param mixed $item New item
*
* @return mixed popped item
*
* @since 1.0.0
*/
public function pushpop($item) public function pushpop($item)
{ {
if (!empty($this->nodes) && ($this->compare)($this->nodes[0], $item) < 0) { if (!empty($this->nodes) && ($this->compare)($this->nodes[0], $item) < 0) {
$temp = $item; $temp = $item;
$item = $this->nodes[0]; $item = $this->nodes[0];
$this->nodes[0] = $temp; $this->nodes[0] = $temp;
$this->siftUp(0); $this->siftUp(0);
} }
@ -118,13 +193,35 @@ class Heap
return $item; return $item;
} }
public function heapify() : void /**
* Turn list into heap
*
* @param array $list Item list
*
* @return void
*
* @since 1.0.0
*/
public function heapify(array $list) : void
{ {
for ($i = (int) \floor(\count($this->nodes) / 2); $i > -1; --$i) { $this->nodes = $list;
for ($i = (int) (\count($this->nodes) / 2); $i > -1; --$i) {
$this->siftUp($i); $this->siftUp($i);
} }
} }
/**
* Update the position of a item
*
* This is called after changing an item
*
* @param mixed $item Item to update
*
* @return bool
*
* @since 1.0.0
*/
public function update($item) : bool public function update($item) : bool
{ {
$pos = null; $pos = null;
@ -152,32 +249,56 @@ class Heap
return true; return true;
} }
/**
* Get n largest items
*
* @param int $n Number of items
*
* @return array
*
* @since 1.0.0
*/
public function getNLargest(int $n) : array public function getNLargest(int $n) : array
{ {
$nodes = $this->nodes; $nodes = $this->nodes;
\uasort($nodes, $this->compare);
return \array_slice(\array_reverse($nodes), 0, $n); return \array_slice(\array_reverse($nodes), 0, $n);
} }
/**
* Get n smalles items
*
* @param int $n Number of items
*
* @return array
*
* @since 1.0.0
*/
public function getNSmallest(int $n): array public function getNSmallest(int $n): array
{ {
$nodes = $this->nodes; $nodes = $this->nodes;
\uasort($nodes, $this->compare);
return \array_slice($nodes, 0, $n); return \array_slice($nodes, 0, $n);
} }
/**
* Down shift
*
* @param int $start Start index
* @param int $pos Pos of the pivot item
*
* @return void
*
* @since 1.0.0
*/
private function siftDown(int $start, int $pos) : void private function siftDown(int $start, int $pos) : void
{ {
$item = $this->nodes[$pos]; $item = $this->nodes[$pos];
while ($pos > $start) { while ($pos > $start) {
$pPos = ($pos - 1) >> 1; $pPos = ($pos - 1) >> 1;
$parent = $this->nodes[$pPos]; $parent = $this->nodes[$pPos];
if (($this->compare)($item, $parent) < 0) { if (($this->compare)($item, $parent) < 0) {
$this->nodes[$pos] = $parent; $this->nodes[$pos] = $parent;
$pos = $pPos; $pos = $pPos;
continue; continue;
} }
@ -188,6 +309,15 @@ class Heap
$this->nodes[$pos] = $item; $this->nodes[$pos] = $item;
} }
/**
* Up shift
*
* @param int $pos Pos of the pivot item
*
* @return void
*
* @since 1.0.0
*/
private function siftUp(int $pos) : void private function siftUp(int $pos) : void
{ {
$ePos = \count($this->nodes); $ePos = \count($this->nodes);
@ -203,30 +333,58 @@ class Heap
} }
$this->nodes[$pos] = $this->nodes[$cPos]; $this->nodes[$pos] = $this->nodes[$cPos];
$pos = $cPos; $pos = $cPos;
$cPos = 2 * $pos + 1; $cPos = 2 * $pos + 1;
} }
$this->nodes[$pos] = $item; $this->nodes[$pos] = $item;
$this->siftDown($sPos, $pos); $this->siftDown($sPos, $pos);
} }
/**
* Clear heap
*
* @return void
*
* @since 1.0.0
*/
public function clear() : void public function clear() : void
{ {
$this->nodes = []; $this->nodes = [];
} }
/**
* Is heap empty?
*
* @return bool
*
* @since 1.0.0
*/
public function isEmpty() : bool public function isEmpty() : bool
{ {
return empty($this->nodes); return empty($this->nodes);
} }
/**
* Get heap size
*
* @return int
*
* @since 1.0.0
*/
public function size() : int public function size() : int
{ {
return \count($this->nodes); return \count($this->nodes);
} }
public function toArray() /**
* Get heap array
*
* @return array
*
* @since 1.0.0
*/
public function toArray() : array
{ {
return $this->nodes; return $this->nodes;
} }

View File

@ -436,32 +436,74 @@ class Graph
return $diameter; return $diameter;
} }
/**
* Get the graph girth
*
* @return int
*
* @since 1.0.0
*/
public function getGirth() : int public function getGirth() : int
{ {
return 0; return 0;
} }
/**
* Get the graph circuit rank
*
* @return int
*
* @since 1.0.0
*/
public function getCircuitRank() : int public function getCircuitRank() : int
{ {
return 0; return 0;
} }
/**
* Get the graph node connectivity
*
* @return int
*
* @since 1.0.0
*/
public function getNodeConnectivity() : int public function getNodeConnectivity() : int
{ {
return 0; return 0;
} }
/**
* Get the graph edge connectivity
*
* @return int
*
* @since 1.0.0
*/
public function getEdgeConnectivity() : int public function getEdgeConnectivity() : int
{ {
return 0; return 0;
} }
/**
* Is the graph connected?
*
* @return bool
*
* @since 1.0.0
*/
public function isConnected() : bool public function isConnected() : bool
{ {
// todo: implement // todo: implement
return true; return true;
} }
/**
* Get unconnected sub graphs
*
* @return Graph[]
*
* @since 1.0.0
*/
public function getUnconnected() : array public function getUnconnected() : array
{ {
// todo: implement // todo: implement
@ -470,18 +512,39 @@ class Graph
return []; return [];
} }
/**
* Is the graph bipartite?
*
* @return bool
*
* @since 1.0.0
*/
public function isBipartite() : bool public function isBipartite() : bool
{ {
// todo: implement // todo: implement
return true; return true;
} }
/**
* Is the graph triangle?
*
* @return bool
*
* @since 1.0.0
*/
public function isTriangleFree() : bool public function isTriangleFree() : bool
{ {
// todo: implement // todo: implement
return true; return true;
} }
/**
* Is the graph circle free?
*
* @return bool
*
* @since 1.0.0
*/
public function isCircleFree() : bool public function isCircleFree() : bool
{ {
// todo: implement // todo: implement

View File

@ -518,6 +518,9 @@ class Directory extends FileAbstract implements FtpContainerInterface, Directory
// todo: add node // todo: add node
} }
/**
* {@inheritdoc}
*/
public function addNode($file) : bool public function addNode($file) : bool
{ {
$this->count += $file->getCount(); $this->count += $file->getCount();

View File

@ -52,6 +52,13 @@ class File extends FileAbstract implements FileInterface
*/ */
private ?Http $uri = null; private ?Http $uri = null;
/**
* Create ftp connection
*
* @param string $path Ftp path including username and password
*
* @since 1.0.0
*/
public function __construct(string $path) public function __construct(string $path)
{ {
$this->uri = new Http($path); $this->uri = new Http($path);

View File

@ -30,13 +30,21 @@ use phpOMS\System\File\StorageAbstract;
*/ */
class FtpStorage extends StorageAbstract class FtpStorage extends StorageAbstract
{ {
/**
* Storage instance.
*
* @var FtpStorage
* @since 1.0.0
*/
private static ?self $instance = null; private static ?self $instance = null;
public function __construct() /**
{ * Get instance.
*
} * @return FtpStorage
*
* @since 1.0.0
*/
public static function getInstance() : StorageAbstract public static function getInstance() : StorageAbstract
{ {
if (self::$instance === null) { if (self::$instance === null) {
@ -46,6 +54,9 @@ class FtpStorage extends StorageAbstract
return self::$instance; return self::$instance;
} }
/**
* {@inheritdoc}
*/
protected static function getClassType(string $path) : string protected static function getClassType(string $path) : string
{ {
return \is_dir($path) || (!\is_file($path) && \stripos($path, '.') === false) ? Directory::class : File::class; return \is_dir($path) || (!\is_file($path) && \stripos($path, '.') === false) ? Directory::class : File::class;

View File

@ -4,7 +4,7 @@
* *
* PHP Version 7.4 * PHP Version 7.4
* *
* @package TBD * @package phpOMS\Utils\IO\Csv
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 1.0
* @version 1.0.0 * @version 1.0.0
@ -12,42 +12,37 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
namespace phpOMS\Utils\IO\Csv { namespace phpOMS\Utils\IO\Csv;
/**
* Cvs interface.
*
* @package phpOMS\Utils\IO\Csv
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
interface CsvInterface
{
/**
* Export Csv.
*
* @param string $path Path to export
*
* @since 1.0.0
* @author Dennis Eichhorn <d.eichhorn@oms.com>
*/
public function exportCsv($path);
/** /**
* Cvs interface. * Import Csv.
* *
* PHP Version 7.4 * @param string $path Path to import
* *
* @package Framework * @return void
* @copyright Dennis Eichhorn *
* @license OMS License 1.0 * @since 1.0.0
* @version 1.0.0 * @author Dennis Eichhorn <d.eichhorn@oms.com>
* @link https://orange-management.org
* @since 1.0.0
*/ */
interface CsvInterface public function importCsv($path) : void;
{
/**
* Export Csv.
*
* @param string $path Path to export
*
* @since 1.0.0
* @author Dennis Eichhorn <d.eichhorn@oms.com>
*/
public function exportCsv($path);
/**
* Import Csv.
*
* @param string $path Path to import
*
* @return void
*
* @since 1.0.0
* @author Dennis Eichhorn <d.eichhorn@oms.com>
*/
public function importCsv($path) : void;
}
} }

View File

@ -15,15 +15,17 @@ declare(strict_types=1);
namespace phpOMS\Utils\IO\Csv; namespace phpOMS\Utils\IO\Csv;
/** /**
* Options trait. * Csv settings.
* *
* @package phpOMS\Utils\IO\Csv * @package phpOMS\Utils\IO\Csv
* @since 1.0.0 * @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/ */
class CsvSettings class CsvSettings
{ {
/** /**
* Get csv file delimiter. * Get csv file delimiter based on file content.
* *
* @param mixed $file File resource * @param mixed $file File resource
* @param int $checkLines Lines to check for evaluation * @param int $checkLines Lines to check for evaluation

View File

@ -4,7 +4,7 @@
* *
* PHP Version 7.4 * PHP Version 7.4
* *
* @package TBD * @package phpOMS\Utils\IO\Excel
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 1.0
* @version 1.0.0 * @version 1.0.0
@ -14,30 +14,217 @@ declare(strict_types=1);
namespace phpOMS\Utils\IO\Excel; namespace phpOMS\Utils\IO\Excel;
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\Utils\IO\IODatabaseMapper; use phpOMS\Utils\IO\IODatabaseMapper;
use phpOMS\Utils\StringUtils;
/**
* Excel database mapper.
*
* @package phpOMS\Utils\IO\Excel
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
class ExcelDatabaseMapper implements IODatabaseMapper class ExcelDatabaseMapper implements IODatabaseMapper
{ {
private $sources = []; /**
* Database connection
*
* @var ConnectionAbstract
* @since 1.0.0
*/
private ConnectionAbstract $con;
private $lineBuffer = 500; /**
* Path to source or destination
*
* @var string
* @since 1.0.0
*/
private string $path = '';
public function addSource(string $source) : void /**
* Constructor.
*
* @param ConnectionAbstract $con Database connection
*
* @since 1.0.0
*/
public function __construct(ConnectionAbstract $con)
{ {
$this->sources[] = $source; $this->con = $con;
} }
public function setLineBuffer(int $buffer) : void /**
* Add path
*
* This is the path of the source data in case of inserting/updating data or the destination file for selecting data.
*
* @param string $path File path
*
* @return void
*
* @since 1.0.0
*/
public function setPath(string $path) : void
{ {
$this->lineBuffer = $buffer; $this->path = $path;
}
public function setSources(array $sources) : void
{
$this->sources = $sources;
} }
/**
* {@inheritdoc}
*/
public function insert() : void public function insert() : void
{ {
$reader = null;
if (StringUtils::endsWith($this->path, '.xlsx')) {
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
} elseif (StringUtils::endsWith($this->path, '.ods')) {
$sheet = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
} else {
$sheet = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
}
$reader->setReadDataOnly(true);
$sheet = $reader->load($this->path);
$tables = $sheet->getSheetCount();
for ($i = 0; $i < $tables; ++$i) {
$sheet->setActiveSheetIndex($i);
$workSheet = $sheet->getSheet($i);
$table = $workSheet->getTitle();
$titles = [];
// get column titles
$column = 1;
while (!empty($value = $workSheet->getCellByColmnAndRow($column, 1)->getValue())) {
$titles[] = $value;
}
$columns = \count($titles);
// insert data
$query = new Builder($this->con);
$query->insert(...$titles)->into($table);
$line = 2;
while (!empty($row = $workSheet->getCellByColumnAndRow(1, $line)->getValue())) {
$cells = [];
for ($j = 1; $j <= $columns; ++$j) {
$cells[] = $workSheet->getCellByColumnAndRow(j, $line)->getValue();
}
$query->values(...$cells);
}
$query->execute();
}
}
/**
* {@inheritdoc}
*/
public function select(array $queries) : void
{
$sheet = new Spreadsheet();
$sheet->getProperties()
->setCreator('Orange-Management')
->setLastModifiedBy('Orange-Management')
->setTitle('Database export')
->setSubject('Database export')
->setDescription('This document is automatically generated from a database export.');
$sheetCount = $sheet->getSheetCount();
foreach ($queries as $key => $query) {
$results = $query->execute()->fetchAll(\PDO::FETCH_ASSOC);
if ($key > $sheetCount - 1) {
$sheet->createSheet($key);
}
$workSheet = $sheet->setActiveSheetIndex($key);
$rows = \count($results);
if ($rows < 1) {
break;
}
$colCount = \count($results[0]);
$columns = \array_keys($results[0]);
// set column titles
for ($i = 1; $i <= $colCount; ++$i) {
$workSheet->setCellValueByColumnAndRow($i, 1, $columns[0][$i - 1]);
}
// set data
foreach ($results as $key => $result) {
for ($i = 1; $i <= $colCount; ++$i) {
$workSheet->setCellValueByColumnAndRow($i, $key + 1, $result[$i - 1]);
}
}
}
if (StringUtils::endsWith($this->path, '.xlsx')) {
(new \PhpOffice\PhpSpreadsheet\Writer\Xlsx())->save($this->path);
} elseif (StringUtils::endsWith($this->path, '.ods')) {
(new \PhpOffice\PhpSpreadsheet\Writer\Ods())->save($this->path);
} else {
(new \PhpOffice\PhpSpreadsheet\Writer\Xls())->save($this->path);
}
}
/**
* {@inheritdoc}
*/
public function update() : void
{
$reader = null;
if (StringUtils::endsWith($this->path, '.xlsx')) {
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
} elseif (StringUtils::endsWith($this->path, '.ods')) {
$sheet = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
} else {
$sheet = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
}
$reader->setReadDataOnly(true);
$sheet = $reader->load($this->path);
$tables = $sheet->getSheetCount();
for ($i = 0; $i < $tables; ++$i) {
$sheet->setActiveSheetIndex($i);
$workSheet = $sheet->getSheet($i);
$table = $workSheet->getTitle();
$titles = [];
// get column titles
$column = 1;
while (!empty($value = $workSheet->getCellByColmnAndRow($column, 1)->getValue())) {
$titles[] = $value;
}
$columns = \count($titles);
// insert data
$line = 2;
while (!empty($row = $workSheet->getCellByColumnAndRow(1, $line)->getValue())) {
$query = new Builder($this->con);
$query->update(...$titles)->into($table);
$cells = [];
for ($j = 1; $j <= $columns; ++$j) {
$cells[] = $workSheet->getCellByColumnAndRow(j, $line)->getValue();
}
$query->values(...$cells)->where($titles[0], '=', $cells[0]);
$query->execute();
}
}
} }
} }

View File

@ -4,7 +4,7 @@
* *
* PHP Version 7.4 * PHP Version 7.4
* *
* @package TBD * @package phpOMS\Utils\IO
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 1.0
* @version 1.0.0 * @version 1.0.0
@ -14,13 +14,42 @@ declare(strict_types=1);
namespace phpOMS\Utils\IO; namespace phpOMS\Utils\IO;
/**
* IO database mapper.
*
* @package phpOMS\Utils\IO
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
interface IODatabaseMapper interface IODatabaseMapper
{ {
public function addSource(string $source); /**
* Insert data from excel sheet into database
*
* @return void
*
* @since 1.0.0
*/
public function insert() : void;
public function setSources(array $sources); /**
* Select data from database and store in excel sheet
*
* @param Builder[] $queries Queries to execute
*
* @return void
*
* @since 1.0.0
*/
public function select(array $queries) : void;
public function setLineBuffer(int $buffer); /**
* Update data from excel sheet into database
public function insert(); *
* @return void
*
* @since 1.0.0
*/
public function update() : void;
} }

View File

@ -68,7 +68,7 @@ class PaginationView extends View
} }
/** /**
* @param int $maxPages * @param int $maxPages Maximum amount of pages to be shown
* *
* @return void * @return void
* *
@ -90,7 +90,7 @@ class PaginationView extends View
} }
/** /**
* @param int $pages * @param int $pages Number of pages
* *
* @return void * @return void
* *
@ -112,7 +112,7 @@ class PaginationView extends View
} }
/** /**
* @param int $page * @param int $page Current page index
* *
* @return void * @return void
* *
@ -134,7 +134,7 @@ class PaginationView extends View
} }
/** /**
* @param int $results * @param int $results Amount of results
* *
* @return void * @return void
* *

View File

@ -1,31 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package phpOMS\Views
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace phpOMS\Views;
/**
* Basic table view which can be used as basis for specific implementations.
*
* @package phpOMS\Views
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
class TableView extends View
{
public function renderHeaderColumn(string $inner, bool $sortable = true, bool $filterable = true) : void
{
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace phpOMS\tests\Math\Integral;
/**
* @internal
*/
class GaussTest extends \PHPUnit\Framework\TestCase
{
public function testPlaceholder() : void
{
self::markTestIncomplete();
}
}