From efc6e7b0c4769ba4cdd469dd9e2384792ce7a59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Danyi?= Date: Tue, 5 Sep 2017 19:15:17 +0200 Subject: [PATCH] * tsp-info endpoint added * different collector services are now implemented --- composer.json | 2 + composer.lock | 109 ++++++++++- config/autoload/local.php.dist | 36 ++++ config/routes.php | 2 + src/App/Action/TspInfoAction.php | 73 ++++++++ src/App/Action/TspInfoFactory.php | 30 +++ src/App/ConfigProvider.php | 4 + src/App/Entity/KanbanBoard.php | 3 + src/App/Entity/TrProgress.php | 114 ++++++++++++ src/App/Entity/VacationDay.php | 94 ++++++++++ src/App/Service/AvatarService.php | 18 ++ src/App/Service/JcatInfoCollectorService.php | 70 +++++++ .../JcatInfoCollectorServiceFactory.php | 18 ++ src/App/Service/JiraCollectorService.php | 41 ++++- src/App/Service/TrInfoCollectorService.php | 172 ++++++++++++++---- .../Service/VacationInfoCollectorService.php | 132 +++++++++++--- 16 files changed, 855 insertions(+), 63 deletions(-) create mode 100644 src/App/Action/TspInfoAction.php create mode 100644 src/App/Action/TspInfoFactory.php create mode 100644 src/App/Entity/TrProgress.php create mode 100644 src/App/Entity/VacationDay.php create mode 100644 src/App/Service/JcatInfoCollectorService.php create mode 100644 src/App/Service/JcatInfoCollectorServiceFactory.php diff --git a/composer.json b/composer.json index 9cca07f..84c73ef 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,9 @@ "require": { "php": "^7.1", "doctrine/common": "^2.8", + "league/csv": "^9.0", "los/basepath": "^1.0", + "meyfa/php-svg": "^0.6.0", "roave/security-advisories": "dev-master", "symfony/console": "^3.3", "symfony/css-selector": "^3.3", diff --git a/composer.lock b/composer.lock index cc8c381..dedde61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "58819bed1efddc237ebfcd76754b3380", + "content-hash": "2c35a874f4da183a1aef96abfbd4ee59", "packages": [ { "name": "container-interop/container-interop", @@ -542,6 +542,70 @@ ], "time": "2017-01-14T15:23:42+00:00" }, + { + "name": "league/csv", + "version": "9.0.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/csv.git", + "reference": "5dc305e7958190bcab0cc2778888a4f658d29aa1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/5dc305e7958190bcab0cc2778888a4f658d29aa1", + "reference": "5dc305e7958190bcab0cc2778888a4f658d29aa1", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=7.0.10" + }, + "require-dev": { + "ext-curl": "*", + "friendsofphp/php-cs-fixer": "^2.0", + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Csv\\": "src" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://github.com/nyamsprod/", + "role": "Developer" + } + ], + "description": "Csv data manipulation made easy in PHP", + "homepage": "http://csv.thephpleague.com", + "keywords": [ + "csv", + "export", + "filter", + "import", + "read", + "write" + ], + "time": "2017-08-21T13:42:10+00:00" + }, { "name": "los/basepath", "version": "1.0.1", @@ -585,6 +649,49 @@ "homepage": "https://github.com/lansoweb/basepath", "time": "2016-08-27T20:56:32+00:00" }, + { + "name": "meyfa/php-svg", + "version": "v0.6.0", + "source": { + "type": "git", + "url": "https://github.com/meyfa/php-svg.git", + "reference": "cde475bf2566d8414fb6d11f55653180203d4e01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/meyfa/php-svg/zipball/cde475bf2566d8414fb6d11f55653180203d4e01", + "reference": "cde475bf2566d8414fb6d11f55653180203d4e01", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "SVG\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabian Meyer", + "homepage": "http://meyfa.net" + } + ], + "description": "Read, edit, write, and render SVG files with PHP", + "homepage": "https://github.com/meyfa/php-svg", + "keywords": [ + "svg" + ], + "time": "2017-07-29T11:10:57+00:00" + }, { "name": "nikic/fast-route", "version": "v1.2.0", diff --git a/config/autoload/local.php.dist b/config/autoload/local.php.dist index 39379d9..4756589 100644 --- a/config/autoload/local.php.dist +++ b/config/autoload/local.php.dist @@ -1,5 +1,6 @@ [ 'jira.user' => '...', 'jira.password' => '...', + 'mhweb.user' => '...', + 'mhweb.password' => '...', + + 'pra.baseData' => [ + 'A' => [ + TrInfo::UNIT_CORE => 0, + TrInfo::UNIT_SIG => 0, + TrInfo::UNIT_TADE => 0, + ], + 'B' => [ + TrInfo::UNIT_CORE => 27, + TrInfo::UNIT_SIG => 3, + TrInfo::UNIT_TADE => 0, + ], + 'C' => [ + TrInfo::UNIT_CORE => 212, + TrInfo::UNIT_SIG => 56, + TrInfo::UNIT_TADE => 9, + ], + ], + 'url.jiraTspExpedites' => [ + "baseUrl" => "https://jirapducc.mo.ca.am.ericsson.se/rest/api/2/search?jql=filter=%s", + "filters" => [ + "unassigned" => 12768, + "all" => 12502, + ] + ], 'url.jiraKanbanBoard' => [ 'baseUrl' => 'https://jirapducc.mo.ca.am.ericsson.se/rest/api/2/search?jql=filter=%s&maxResults=1000&fields=%s', 'filterId' => 14229, @@ -35,7 +63,15 @@ return [ 'customfield_11692', ], ], + 'url.mhWebPraGoals' => 'https://mhweb.ericsson.se:443/SearchWeb/faces/search/query/resultPage.xhtml?&v=3&queryKey=74023&output=CSV&csvDelimiter=COMMA', + 'url.mhWebTrProgress' => 'https://mhweb.ericsson.se:443/SearchWeb/faces/search/query/resultPage.xhtml?&v=3&queryKey=68655&output=CSV&csvDelimiter=COMMA', + 'url.mhWebTrEdit' => 'https://mhweb.ericsson.se/TREditWeb/faces/tredit/tredit.xhtml?eriref=%s', 'url.labTemperatureUrl' => 'https://159.107.194.61/public/mapshow_simple.htm?id=3381&mapid=884B46A7-AE59-4523-9981-8E9FEB7C1FCF', + 'url.vacation' => 'https://rhp.common.hu.eld.ericsson.se/vacation.php?action=groupview&dm_h=2&dm_v=1&group_id=478', + 'url.jcatTrFlow' => "http://jcat.tsp.eth.ericsson.se:8080/Trweb/trflow/reader.php?query=SELECT+*+FROM+trinfo+where+validationerrors+!=+''", + + 'url.eurestCamera2' => 'https://auto:auto@91.82.89.112:8443/mjpg/video.mjpg', + 'http.proxy.enabled' => false, 'http.proxy.type' => CURLPROXY_SOCKS5, 'http.proxy.url' => "localhost:1080", diff --git a/config/routes.php b/config/routes.php index 55688f9..9a12990 100644 --- a/config/routes.php +++ b/config/routes.php @@ -31,3 +31,5 @@ $app->get('/api/ping', App\Action\PingAction::class, 'api.ping'); $app->get('/api/kanban', App\Action\KanbanAction::class, 'api.kanban'); $app->get('/avatars/{signum}', App\Action\AvatarAction::class, 'user.avatar'); + +$app->get('/api/tsp-info', App\Action\TspInfoAction::class, 'api.tsp-info'); diff --git a/src/App/Action/TspInfoAction.php b/src/App/Action/TspInfoAction.php new file mode 100644 index 0000000..5ddd1ed --- /dev/null +++ b/src/App/Action/TspInfoAction.php @@ -0,0 +1,73 @@ +vacationInfoCollectorService = $vacationInfoCollectorService; + $this->trInfoCollectorService = $trInfoCollectorService; + $this->jcatInfoCollectorService = $jcatInfoCollectorService; + $this->labInfoCollectorService = $labInfoCollectorService; + $this->jiraCollectorService = $jiraCollectorService; + } + + /** + * @param ServerRequestInterface $request + * @param DelegateInterface $delegate + * @return JsonCorsResponse + * @todo lab temperature data + */ + public function process(ServerRequestInterface $request, DelegateInterface $delegate) + { + return new JsonCorsResponse([ + 'animGifs' => [], + 'praGoals' => $this->trInfoCollectorService->getPraGoals(), + 'trProgress' => $this->trInfoCollectorService->getProgressInfo(), + 'trFlow' => $this->jcatInfoCollectorService->getTrFlow(), + 'expedites' => $this->jiraCollectorService->getExpedites(), + 'vacationInfo' => $this->vacationInfoCollectorService->isVacationSoon(), + 'labTemperature' => $this->labInfoCollectorService->getLabTemperatureData(), + ]); + } +} diff --git a/src/App/Action/TspInfoFactory.php b/src/App/Action/TspInfoFactory.php new file mode 100644 index 0000000..70c9234 --- /dev/null +++ b/src/App/Action/TspInfoFactory.php @@ -0,0 +1,30 @@ +get(VacationInfoCollectorService::class); + $trInfoCollectorService = $container->get(TrInfoCollectorService::class); + $jcatInfoCollectorService = $container->get(JcatInfoCollectorService::class); + $labInfoCollectorService = $container->get(LabInfoCollectorService::class); + $jiraInfoCollectorService = $container->get(JiraCollectorService::class); + + return new TspInfoAction( + $dataCollectorService, + $trInfoCollectorService, + $jcatInfoCollectorService, + $labInfoCollectorService, + $jiraInfoCollectorService + ); + } +} diff --git a/src/App/ConfigProvider.php b/src/App/ConfigProvider.php index e6f7fb8..d3aa3a3 100644 --- a/src/App/ConfigProvider.php +++ b/src/App/ConfigProvider.php @@ -46,10 +46,14 @@ class ConfigProvider Action\AvatarAction::class => Action\AvatarFactory::class, Action\HomePageAction::class => Action\HomePageFactory::class, Action\KanbanAction::class => Action\KanbanFactory::class, + Action\TspInfoAction::class => Action\TspInfoFactory::class, Service\AvatarService::class => Service\AvatarServiceFactory::class, Service\JiraCollectorService::class => Service\JiraCollectorServiceFactory::class, Service\LabInfoCollectorService::class => Service\LabInfoCollectorServiceFactory::class, + Service\VacationInfoCollectorService::class => Service\VacationInfoCollectorServiceFactory::class, + Service\TrInfoCollectorService::class => Service\TrInfoCollectorServiceFactory::class, + Service\JcatInfoCollectorService::class => Service\JcatInfoCollectorServiceFactory::class, 'service.avatarCache' => function(ContainerInterface $container): StorageInterface { $cache = new FilesytemCache(); diff --git a/src/App/Entity/KanbanBoard.php b/src/App/Entity/KanbanBoard.php index 47a96a4..e1848fb 100644 --- a/src/App/Entity/KanbanBoard.php +++ b/src/App/Entity/KanbanBoard.php @@ -234,6 +234,9 @@ class KanbanBoard implements \JsonSerializable */ private function updatedAtReverseSort(array $toSort): array { + $toSort = array_filter($toSort, function(KanbanEntry $item){ + return $item->getAssignee() != null; + }); usort($toSort, function(KanbanEntry $a, KanbanEntry $b){ return $b->getUpdatedAt() <=> $a->getUpdatedAt(); }); diff --git a/src/App/Entity/TrProgress.php b/src/App/Entity/TrProgress.php new file mode 100644 index 0000000..73b4ffd --- /dev/null +++ b/src/App/Entity/TrProgress.php @@ -0,0 +1,114 @@ +eriref; + } + + /** + * @param string $eriref + * @return TrProgress + */ + public function setEriref(string $eriref): TrProgress + { + $this->eriref = $eriref; + return $this; + } + + /** + * @return string + */ + public function getHeading(): string + { + return $this->heading; + } + + /** + * @param string $heading + * @return TrProgress + */ + public function setHeading(string $heading): TrProgress + { + $this->heading = $heading; + return $this; + } + + /** + * @return string + */ + public function getPrio(): string + { + return $this->prio; + } + + /** + * @param string $prio + * @return TrProgress + */ + public function setPrio(string $prio): TrProgress + { + $this->prio = $prio; + return $this; + } + + /** + * @return int + */ + public function getLastProgress(): int + { + return $this->lastProgress; + } + + /** + * @param int $lastProgress + * @return TrProgress + */ + public function setLastProgress(int $lastProgress): TrProgress + { + $this->lastProgress = $lastProgress; + return $this; + } + + + + /** + * @return array + */ + function jsonSerialize() + { + return [ + 'eriref' => $this->getEriref(), + 'heading' => $this->getHeading(), + 'prio' => $this->getPrio(), + 'lastProgress' => $this->getLastProgress(), + ]; + } +} diff --git a/src/App/Entity/VacationDay.php b/src/App/Entity/VacationDay.php new file mode 100644 index 0000000..420e004 --- /dev/null +++ b/src/App/Entity/VacationDay.php @@ -0,0 +1,94 @@ +signums = new ArrayCollection(); + } + + /** + * @return int + */ + public function getDay(): int + { + return $this->day; + } + + /** + * @param int $day + * @return VacationDay + */ + public function setDay(int $day): VacationDay + { + $this->day = $day; + return $this; + } + + /** + * @return ArrayCollection|string[] + */ + public function getSignums() + { + return $this->signums; + } + + /** + * @param ArrayCollection|string[] $signums + * @return VacationDay + */ + public function setSignums($signums): VacationDay + { + $this->signums = $signums; + return $this; + } + + /** + * @param string $signum + * @return VacationDay + */ + public function addSignum(string $signum): VacationDay + { + if(!$this->signums->contains($signum)) { + $this->signums->add($signum); + } + return $this; + } + + /** + * @param string $signum + * @return VacationDay + */ + public function removeSignum(string $signum): VacationDay + { + if($this->signums->contains($signum)) { + $this->signums->removeElement($signum); + } + return $this; + } + + /** + * @return array + */ + function jsonSerialize() + { + return [ + 'day' => $this->getDay(), + 'signums' => $this->getSignums()->getValues(), + ]; + } +} diff --git a/src/App/Service/AvatarService.php b/src/App/Service/AvatarService.php index f3ddee8..836846d 100644 --- a/src/App/Service/AvatarService.php +++ b/src/App/Service/AvatarService.php @@ -4,6 +4,8 @@ namespace App\Service; use Zend\Cache\Storage\StorageInterface; use Zend\Config\Config; +use Zend\Diactoros\Response; +use Zend\Diactoros\Response\TextResponse; use Zend\Expressive\Router\RouterInterface; use Zend\Http\Client; @@ -72,6 +74,8 @@ class AvatarService } /** + * Returns avatar image data as string + * * @param string $signum * @return string */ @@ -83,4 +87,18 @@ class AvatarService return $this->cache->getItem($signum); } + + public function getUserAvatarResponse(string $signum) + { + $localAvatarFile = "public/avatars/$signum"; + if(file_exists($localAvatarFile)) { + $fp = fopen($localAvatarFile,"r+"); + $response = new Response($fp); + } else { + $response = new TextResponse($this->getAvatarData($signum)); + } + + return $response + ->withHeader('Content-type', 'image/png'); + } } diff --git a/src/App/Service/JcatInfoCollectorService.php b/src/App/Service/JcatInfoCollectorService.php new file mode 100644 index 0000000..5f191b1 --- /dev/null +++ b/src/App/Service/JcatInfoCollectorService.php @@ -0,0 +1,70 @@ +httpClient = $client; + $this->config = $config; + } + + public function getTrFlow() + { + /** @var Config $kanbanBoardUriParams */ + $trFlowUri = $this->config->get('url.jcatTrFlow'); + + $response = $this->httpClient + ->setUri($trFlowUri) + ->send(); + + if (!$response->isSuccess()) { + throw new \UnexpectedValueException("Bad JCAT result", $response->getStatusCode()); + } + + return $this->parseFlowHtmlResult($response->getBody()); + } + + private function parseFlowHtmlResult(string $html) + { + $xmlErrorHandling = libxml_use_internal_errors(TRUE); + $domDocument = new \DOMDocument(); + $domDocument->loadHTML($html); + libxml_clear_errors(); + libxml_use_internal_errors($xmlErrorHandling); + + $documentXpath = new \DOMXPath($domDocument); + /** @var \DOMNodeList $elements */ + $elements = $documentXpath->query('//tr/td[1]'); + + $result = []; + /** @var \DOMElement $element */ + foreach ($elements as $element) { + $result[] = trim($element->nodeValue); + } + + return array_count_values($result); + } +} diff --git a/src/App/Service/JcatInfoCollectorServiceFactory.php b/src/App/Service/JcatInfoCollectorServiceFactory.php new file mode 100644 index 0000000..97dd81c --- /dev/null +++ b/src/App/Service/JcatInfoCollectorServiceFactory.php @@ -0,0 +1,18 @@ +get('config'); + $httpClient = $container->get(Client::class); + $config = new Config($configArray['app.config']); + return new JcatInfoCollectorService($httpClient, $config); + } +} diff --git a/src/App/Service/JiraCollectorService.php b/src/App/Service/JiraCollectorService.php index 621f15f..1bb9925 100644 --- a/src/App/Service/JiraCollectorService.php +++ b/src/App/Service/JiraCollectorService.php @@ -41,6 +41,45 @@ class JiraCollectorService $this->config = $config; } + /** + * @return array + */ + public function getExpedites(): array + { + $user = $this->config->get('jira.user'); + $password = $this->config->get('jira.password'); + /** @var Config $expediteUriParams */ + $expediteUriParams = $this->config->get('url.jiraTspExpedites'); + + $result = []; + foreach ($expediteUriParams['filters'] as $type => $filterId) { + + $jiraResultUri = sprintf( + $expediteUriParams['baseUrl'], + $filterId + ); + + $response = $this->httpClient + ->setUri($jiraResultUri) + ->setAuth($user, $password) + ->send(); + + if(!$response->isSuccess()) { + throw new \UnexpectedValueException( + sprintf("Bad JIRA result when trying to load: %s\n%s", + $jiraResultUri, + $response->getBody() + ), + $response->getStatusCode() + ); + } + + $parsedJsonData = Decoder::decode($response->getBody(), Json::TYPE_OBJECT); + $result[$type] = $parsedJsonData->total; + } + return $result; + } + /** * @return KanbanBoard */ @@ -58,8 +97,8 @@ class JiraCollectorService ); $response = $this->httpClient - ->setAuth($user, $password) ->setUri($kanbanBoardUri) + ->setAuth($user, $password) ->send(); if(!$response->isSuccess()) { diff --git a/src/App/Service/TrInfoCollectorService.php b/src/App/Service/TrInfoCollectorService.php index 935a757..6b7d52e 100644 --- a/src/App/Service/TrInfoCollectorService.php +++ b/src/App/Service/TrInfoCollectorService.php @@ -2,12 +2,27 @@ namespace App\Service; -use Symfony\Component\CssSelector\CssSelectorConverter; +use App\Entity\TrProgress; +use League\Csv\Reader; +use League\Csv\Statement; use Zend\Config\Config; use Zend\Http\Client; class TrInfoCollectorService { + const UNIT_CORE = 'core'; + const UNIT_SIG = 'sig'; + const UNIT_TADE = 'tade'; + + const MHO_MAP = [ + 'ETH-TSPCW-D' => self::UNIT_CORE, + 'ETH-TSPCORE' => self::UNIT_CORE, + 'XTS-TSP-SIG' => self::UNIT_SIG, + 'XTS-TSPSIGD' => self::UNIT_SIG, + 'ETH-TADE-DE' => self::UNIT_TADE, + 'ETH-TADE-MA' => self::UNIT_TADE, + ]; + /** * @var Config */ @@ -18,15 +33,6 @@ class TrInfoCollectorService */ private $httpClient; - /** - * @var array - */ - private $tempSensors = [ - 'Temp 5' => 'back_left', - 'Temp 4' => 'back_middle', - 'Temp 3' => 'back_right', - ]; - /** * JiraClientService constructor. * @param Client $client @@ -38,49 +44,139 @@ class TrInfoCollectorService $this->config = $config; } - public function getLabTemperatureData() + /** + * @return array + */ + public function getProgressInfo() { - /** @var Config $labTemperatureUrl */ - $labTemperatureUrl = $this->config->get('url.labTemperatureUrl'); + $user = $this->config->get('mhweb.user'); + $password = $this->config->get('mhweb.password'); + /** @var string $trProgressUri */ + $trProgressUri = $this->config->get('url.mhWebTrProgress'); $response = $this->httpClient - ->setUri($labTemperatureUrl) + ->setAuth($user, $password) + ->setUri($trProgressUri) ->send(); - if(!$response->isSuccess()) { - throw new \UnexpectedValueException("Bad LAB result", $response->getStatusCode()); + if (!$response->isSuccess()) { + throw new \UnexpectedValueException("Bad MHWEB result", $response->getStatusCode()); } - return $this->parseHtml($response->getBody()); + $csvResponse = $response->getBody(); + $csvReader = Reader::createFromString($csvResponse); + $csvReader->setHeaderOffset(0); + + return $this->parseProgressCsvRecords($csvReader); } - private function parseHtml($html): array + public function getPraGoals() { - $cssToXpathConverter = new CssSelectorConverter(); - $xpathLabelQuery = $cssToXpathConverter->toXPath('a.sensormenu.isnotpaused'); - $xpathValueQuery = $cssToXpathConverter->toXPath('div.graphlabel2'); + $user = $this->config->get('mhweb.user'); + $password = $this->config->get('mhweb.password'); + /** @var string $trProgressUri */ + $trProgressUri = $this->config->get('url.mhWebPraGoals'); - $xmlErrorHandling = libxml_use_internal_errors(TRUE); - $domDocument = new \DOMDocument(); - $domDocument->loadHTML($html); - libxml_clear_errors(); - libxml_use_internal_errors($xmlErrorHandling); + $response = $this->httpClient + ->setAuth($user, $password) + ->setUri($trProgressUri) + ->send(); - $documentXpath = new \DOMXPath($domDocument); - /** @var \DOMNodeList $element */ - $element = $documentXpath->query($xpathLabelQuery); + if (!$response->isSuccess()) { + throw new \UnexpectedValueException("Bad MHWEB result", $response->getStatusCode()); + } - $thing = []; - /** @var \DOMElement $item */ - foreach($element as $item) { - $sensorName = trim($item->nodeValue); - if( in_array($sensorName, array_keys($this->tempSensors)) ){ - /** @var \DOMNodeList $element */ - $valueElement = $documentXpath->query($xpathValueQuery, $item->parentNode->parentNode); - $thing[$this->tempSensors[$sensorName]] = $valueElement->item(0)->nodeValue; + $csvResponse = $response->getBody(); + $csvReader = Reader::createFromString($csvResponse); + $csvReader->setHeaderOffset(0); + + $statement = new Statement(); + $csvRecords = $statement + ->process($csvReader); + + $goalCounter = $this->initGoalCounter(); + + foreach ($csvRecords as $record) { + $goalCounter[self::MHO_MAP[$record["mho"]]][$record["prio"]]++; + } + + return $this->caltulatePraBaseDiff($goalCounter); + } + + private function caltulatePraBaseDiff($goalCounter): array + { + $praBaseData = $this->config->get('pra.baseData'); + foreach ($goalCounter as $mho => &$counters) { + foreach (['A', 'B', 'C'] as $prio) { + $counters[$prio] = $counters[$prio] - $praBaseData[$mho][$prio]; + } + } + return $goalCounter; + } + + private function parseProgressCsvRecords(Reader $csvReader) + { + $statement = new Statement(); + $csvRecords = $statement + ->process($csvReader); + + $trProgressList = []; + + foreach ($csvRecords as $csvRecord) { + $trProgress = new TrProgress(); + $trProgress->setEriref($csvRecord["eriref"]) + ->setHeading($csvRecord["heading"]) + ->setPrio($csvRecord["prio"]) + ->setLastProgress($this->getLastProgressInDay($csvRecord)) + ; + + $trProgressList[] = $trProgress; + } + + usort($trProgressList, function(TrProgress $a, TrProgress $b){ + return $b->getLastProgress() <=> $a->getLastProgress(); + }); + + return $trProgressList; + } + + /** + * @param array $csvRecord + * @return int + * @todo fix the BS with tuesday or whatever + */ + private function getLastProgressInDay(array $csvRecord): int + { + $lastProgressDate = null; + $hasNoProgressDate = false; + try { + $lastProgressDate = new \DateTime(str_replace(" - "," ", $csvRecord["lastprogressdate"])); + } catch(\Exception $e) { + $hasNoProgressDate = true; + } + try { + $lastDesignDate = new \DateTime($csvRecord["lastdesigndate"]); + if($hasNoProgressDate || $lastDesignDate > $lastProgressDate) { + $lastProgressDate = $lastDesignDate; + } + } catch (\Exception $e) { + if($hasNoProgressDate) { + return 0; } } - return $thing; + $now = new \DateTime(); + $dateDiff = $now->diff($lastProgressDate); + return $dateDiff->days; + } + + private function initGoalCounter(): array + { + $emptyPrios = ['A' => 0, 'B' => 0, 'C' => 0]; + return [ + self::UNIT_CORE => $emptyPrios, + self::UNIT_SIG => $emptyPrios, + self::UNIT_TADE => $emptyPrios, + ]; } } diff --git a/src/App/Service/VacationInfoCollectorService.php b/src/App/Service/VacationInfoCollectorService.php index af0dc75..8981b3b 100644 --- a/src/App/Service/VacationInfoCollectorService.php +++ b/src/App/Service/VacationInfoCollectorService.php @@ -2,7 +2,11 @@ namespace App\Service; -use Symfony\Component\CssSelector\CssSelectorConverter; +use App\Entity\VacationDay; +use Doctrine\Common\Collections\ArrayCollection; +use SVG\Nodes\Embedded\SVGImageElement; +use SVG\Nodes\Shapes\SVGRect; +use SVG\SVGImage; use Zend\Config\Config; use Zend\Http\Client; @@ -19,13 +23,9 @@ class VacationInfoCollectorService private $httpClient; /** - * @var array + * @var VacationDay[]|ArrayCollection */ - private $tempSensors = [ - 'Temp 5' => 'back_left', - 'Temp 4' => 'back_middle', - 'Temp 3' => 'back_right', - ]; + private $vacations; /** * JiraClientService constructor. @@ -36,29 +36,71 @@ class VacationInfoCollectorService { $this->httpClient = $client; $this->config = $config; + $this->vacations = new ArrayCollection(); } - public function getLabTemperatureData() + /** + * @return bool + */ + public function isVacationSoon(): bool { - /** @var Config $labTemperatureUrl */ - $labTemperatureUrl = $this->config->get('url.labTemperatureUrl'); + return count($this->getVacationData()) > 0; + } + + /** + * @return string + */ + public function createVacationSvgImage(): string + { + $vacationData = $this->getVacationData(); + $svgImage = new SVGImage(1000,400); + + + $doc = $svgImage->getDocument(); + + for ($i = 0; $i<5; $i++) { + for($j=0; $j<3; $j++) { + $rect = new SVGRect($i*40+5*$i+5, 40*$j+5*$j+5, 40, 40); + $rect->setStyle('fill', '#0000FF'); + + $img = new SVGImageElement("/avatars/edvidan", $i*40+5*($i+1), 40*$j+5*$j+5, 20,20); + + $doc->addChild($rect) + ->addChild($img); + } + } + + + + + // blue 40x40 square at (0, 0) + + return $svgImage; + } + + public function getVacationData() + { + /** @var Config $vacationPageUrl */ + $vacationPageUrl = $this->config->get('url.vacation'); $response = $this->httpClient - ->setUri($labTemperatureUrl) + ->setUri($vacationPageUrl) ->send(); if(!$response->isSuccess()) { - throw new \UnexpectedValueException("Bad LAB result", $response->getStatusCode()); + throw new \UnexpectedValueException("Bad vacation result", $response->getStatusCode()); } return $this->parseHtml($response->getBody()); } + /** + * @param $html + * @return VacationDay[] + */ private function parseHtml($html): array { - $cssToXpathConverter = new CssSelectorConverter(); - $xpathLabelQuery = $cssToXpathConverter->toXPath('a.sensormenu.isnotpaused'); - $xpathValueQuery = $cssToXpathConverter->toXPath('div.graphlabel2'); + $peopleQuery = '//table[@class="vacation"]//td[@class="v_user_h"]'; $xmlErrorHandling = libxml_use_internal_errors(TRUE); $domDocument = new \DOMDocument(); @@ -68,19 +110,63 @@ class VacationInfoCollectorService $documentXpath = new \DOMXPath($domDocument); /** @var \DOMNodeList $element */ - $element = $documentXpath->query($xpathLabelQuery); + $element = $documentXpath->query($peopleQuery); + + $now = new \DateTime(); + $todaysDayNumber = intval($now->format("d")); + $todaysWeekDay = intval($now->format("N")); + + $thisWeekFirstDay = $todaysDayNumber - $todaysWeekDay + 1; + $thisWeekLastDay = $thisWeekFirstDay + 4; + $nextWeekFirstDay = $thisWeekFirstDay + 7; + $nextWeekLastDay = $nextWeekFirstDay + 4; - $thing = []; /** @var \DOMElement $item */ foreach($element as $item) { - $sensorName = trim($item->nodeValue); - if( in_array($sensorName, array_keys($this->tempSensors)) ){ - /** @var \DOMNodeList $element */ - $valueElement = $documentXpath->query($xpathValueQuery, $item->parentNode->parentNode); - $thing[$this->tempSensors[$sensorName]] = $valueElement->item(0)->nodeValue; + $thisWeekFirstDay = ($thisWeekFirstDay < 1) + ? 1 + : $thisWeekFirstDay; + $dateCells = $documentXpath->query('..//td', $item); + +// $user = trim($dateCells->item(0)->textContent); + $signumHref = $dateCells->item(0)->firstChild->getAttribute('href'); + preg_match("/id=(.*)$/msi",$signumHref,$matchResult); + $signum = $matchResult[1]; + + + for($i = $thisWeekFirstDay; $i < $thisWeekLastDay+1; $i++) { + $vacationDay = $this->getVacationDay($i); + $isVacation = $documentXpath->query( + './/div[@class="book book_n_v"]', + $dateCells->item($i) + ); + if ($isVacation->length) { + $vacationDay->addSignum($signum); + } + } + + for($i=$nextWeekFirstDay; $i<$nextWeekLastDay+1; $i++) { + $vacationDay = $this->getVacationDay($i); + $isVacation = $documentXpath->query( + './/div[@class="book book_n_v"]', + $dateCells->item($i) + ); + if ($isVacation->length) { + $vacationDay->addSignum($signum); + } } } - return $thing; + return $this->vacations->filter(function(VacationDay $item){ + return count($item->getSignums()); + })->getValues(); + } + + private function getVacationDay(int $day): VacationDay + { + if(!isset($this->vacations[$day])) { + $this->vacations[$day] = (new VacationDay())->setDay($day); + } + return $this->vacations[$day]; } }