* tsp-info endpoint added

* different collector services are now implemented
This commit is contained in:
Dávid Danyi 2017-09-05 19:15:17 +02:00
parent 88527e4ff1
commit efc6e7b0c4
16 changed files with 855 additions and 63 deletions

View File

@ -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",

109
composer.lock generated
View File

@ -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",

View File

@ -1,5 +1,6 @@
<?php
use \App\Service\TrInfoCollectorService as TrInfo;
/**
* Local configuration.
*
@ -11,6 +12,33 @@ return [
'app.config' => [
'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",

View File

@ -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');

View File

@ -0,0 +1,73 @@
<?php
namespace App\Action;
use App\Response\JsonCorsResponse;
use App\Service\JcatInfoCollectorService;
use App\Service\JiraCollectorService;
use App\Service\LabInfoCollectorService;
use App\Service\TrInfoCollectorService;
use App\Service\VacationInfoCollectorService;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
class TspInfoAction implements ServerMiddlewareInterface
{
/**
* @var VacationInfoCollectorService
*/
private $vacationInfoCollectorService;
/**
* @var TrInfoCollectorService
*/
private $trInfoCollectorService;
/**
* @var JcatInfoCollectorService
*/
private $jcatInfoCollectorService;
/**
* @var LabInfoCollectorService
*/
private $labInfoCollectorService;
/**
* @var JiraCollectorService
*/
private $jiraCollectorService;
public function __construct(VacationInfoCollectorService $vacationInfoCollectorService,
TrInfoCollectorService $trInfoCollectorService,
JcatInfoCollectorService $jcatInfoCollectorService,
LabInfoCollectorService $labInfoCollectorService,
JiraCollectorService $jiraCollectorService)
{
$this->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(),
]);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Action;
use App\Service\JcatInfoCollectorService;
use App\Service\JiraCollectorService;
use App\Service\LabInfoCollectorService;
use App\Service\TrInfoCollectorService;
use App\Service\VacationInfoCollectorService;
use Interop\Container\ContainerInterface;
class TspInfoFactory
{
public function __invoke(ContainerInterface $container)
{
$dataCollectorService = $container->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
);
}
}

View File

@ -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();

View File

@ -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();
});

View File

@ -0,0 +1,114 @@
<?php
namespace App\Entity;
class TrProgress implements \JsonSerializable
{
/**
* @var string
*/
private $eriref;
/**
* @var string
*/
private $heading;
/**
* @var string
*/
private $prio;
/**
* @var int
*/
private $lastProgress;
/**
* @return string
*/
public function getEriref(): string
{
return $this->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(),
];
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class VacationDay implements \JsonSerializable
{
/**
* @var int
*/
private $day;
/**
* @var string[]|ArrayCollection
*/
private $signums;
public function __construct()
{
$this->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(),
];
}
}

View File

@ -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');
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Service;
use League\Csv\Reader;
use League\Csv\Statement;
use Zend\Config\Config;
use Zend\Http\Client;
class JcatInfoCollectorService
{
/**
* @var Config
*/
private $config;
/**
* @var Client
*/
private $httpClient;
/**
* JiraClientService constructor.
* @param Client $client
* @param Config $config
*/
public function __construct(Client $client, Config $config)
{
$this->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);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Service;
use Interop\Container\ContainerInterface;
use Zend\Config\Config;
use Zend\Http\Client;
class JcatInfoCollectorServiceFactory
{
public function __invoke(ContainerInterface $container)
{
$configArray = $container->get('config');
$httpClient = $container->get(Client::class);
$config = new Config($configArray['app.config']);
return new JcatInfoCollectorService($httpClient, $config);
}
}

View File

@ -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()) {

View File

@ -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,
];
}
}

View File

@ -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];
}
}