* tsp-info endpoint added
* different collector services are now implemented
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
70
src/App/Service/JcatInfoCollectorService.php
Normal file
70
src/App/Service/JcatInfoCollectorService.php
Normal 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);
|
||||
}
|
||||
}
|
||||
18
src/App/Service/JcatInfoCollectorServiceFactory.php
Normal file
18
src/App/Service/JcatInfoCollectorServiceFactory.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user