src/FlexApp/Service/ConsSchedule.php line 125

Open in your IDE?
  1. <?php
  2. namespace FlexApp\Service;
  3. use Exception;
  4. use FlexApp\Events\Style43\GeneralErrorEvent;
  5. use Psr\Cache\InvalidArgumentException;
  6. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  7. use WebBundle\Exception\PortalHelperException;
  8. use WebBundle\Helper\PortalHelper;
  9. class ConsSchedule
  10. {
  11.     private $schedule;
  12.     /**
  13.      * @var PortalHelper
  14.      */
  15.     private $portalHelper;
  16.     /**
  17.      * @var EventDispatcherInterface
  18.      */
  19.     private $eventDispatcher;
  20.     /**
  21.      * @var ParametersProvider
  22.      */
  23.     private $parametersProvider;
  24.     /**
  25.      * @var TranslatorWrapper
  26.      */
  27.     private $translatorWrapper;
  28.     /**
  29.      * @var ChatBCachePool
  30.      */
  31.     private $chatBCachePool;
  32.     public function __construct(
  33.         PortalHelper $portalHelper,
  34.         EventDispatcherInterface $eventDispatcher,
  35.         ParametersProvider $parametersProvider,
  36.         TranslatorWrapper $translatorWrapper,
  37.         ChatBCachePool $chatBCachePool
  38.     ) {
  39.         $this->portalHelper $portalHelper;
  40.         $this->eventDispatcher $eventDispatcher;
  41.         $this->parametersProvider $parametersProvider;
  42.         $this->translatorWrapper $translatorWrapper;
  43.         $this->chatBCachePool $chatBCachePool;
  44.     }
  45.     /**
  46.      * @return array
  47.      *
  48.      * @throws PortalHelperException
  49.      */
  50.     private function getScheduleFromPortal()
  51.     {
  52.         //Получаем график работы всех консультантов с портала и смены одинаковых записей, но с разным временем
  53.         return $this->schedule $this->selfUnion($this->portalHelper->getConsultantsSchedule());
  54.     }
  55.     /**
  56.      * Если один раз получили расписание именно с портала (а не из файлового кеша) - записываем в файловый кеш, чтобы в следующий раз за время жизни кеша (оптимально варьировать от 5 до 60 минут) не дергать портал. И сразу же достаем из файлового кеша.
  57.      * Если один раз получили расписание из файлового кеша - записываем расписание в свойство объекта, чтоб в следующий раз за период отработки скрипта не дергать файловый кеш. Это будет аналогом кеша в оперативной памяти на время жизни скрипта, а точнее - на время жизни php-объекта. Но в данном случае объект живет до тех пор, пока не завершится дочерний процесс чата - обычно это не больше 2 секунд. Но за одну отработку скрипта получение расписание из объекта может идти несколько раз (приветственное сообщение + для расчета признака онлайн/оффлайн в обычных сообщениях консультанта).
  58.      *
  59.      * @throws PortalHelperException
  60.      * @throws InvalidArgumentException
  61.      */
  62.     public function getSchedule()
  63.     {
  64.         if (null === $this->schedule) {
  65.             if ($this->parametersProvider->getParameter('enable_consultants_schedule_caching')) {
  66.                 $scheduleCacheItem $this->chatBCachePool->getPool()->getItem('schedule');
  67.                 //Если нет кеша с расписанием или он истёк - получаем расписание с портала и кешируем в файловой системе
  68.                 if (!$scheduleCacheItem->isHit()) {
  69.                     $scheduleCacheItem->set($this->getScheduleFromPortal());
  70.                     $this->chatBCachePool->getPool()->save($scheduleCacheItem);
  71.                     $scheduleCacheItem $this->chatBCachePool->getPool()->getItem('schedule');
  72.                 }
  73.                 $this->schedule $scheduleCacheItem->get();
  74.             } else {
  75.                 $this->schedule $this->getScheduleFromPortal();
  76.             }
  77.         }
  78.         $timezones = [];
  79.         foreach ($this->schedule['result']['consultData'] ?? [] as $data) {
  80.             $timezones[] = $data['timezone'] ?? null;
  81.         }
  82.         $timezones array_unique($timezones);
  83.         return $this->schedule;
  84.     }
  85.     private function getFirstScheduleArrayByOnlyConsLogin(array $initialConsultDatastring $consLogin): ?array
  86.     {
  87.         foreach ($initialConsultData as $val) {
  88.             if ($val['login'] === $consLogin) {
  89.                 return $val;
  90.             }
  91.         }
  92.         return null;
  93.     }
  94.     /**
  95.      * @return array - возвращает массив c 3 парами ключ-значение. Ключи: work_hours_string, work_days_string, timezone_string
  96.      *
  97.      * @throws InvalidArgumentException
  98.      */
  99.     public function getScheduleByConsLoginAndCountry(string $consLoginstring $countrystring $countryByIpstring $locale): array
  100.     {
  101.         $defaultData = [ //на случай, если в портальном массиве не будет этих данных или вообще не получится получить данные с портала
  102.             'work_hours_string' => '',
  103.             'work_days_string'  => '',
  104.             'timezone_string'   => '',
  105.         ];
  106.         $country $this->modifyCountry($country$countryByIp);
  107.         try {
  108.             $schedule $this->getSchedule();
  109.         } catch (PortalHelperException $e) {
  110.             return $defaultData;
  111.         }
  112.         $consultData $schedule['result']['consultData'] ?? [];
  113.         list($initialConsultData$consultData$key) = $this->modifyConsultDataArrayContent($consLogin$country$consultData);
  114.         if (!isset($consultData[$key])) {
  115.             //В этом случае (когда не нашли по логину+стране) надо сначала проверить есть ли расписание по логину хотя бы по какой-то стране. Если есть - то взять по первой в списке стране.
  116.             $scheduleArrayByConsLogin $this->getFirstScheduleArrayByOnlyConsLogin($initialConsultData$consLogin);
  117.             if (is_array($scheduleArrayByConsLogin) && count($scheduleArrayByConsLogin)) {
  118.                 $consultData[$key] = $scheduleArrayByConsLogin;
  119.             } else {
  120.                 return $defaultData;
  121.             }
  122.         }
  123.         $consSchedule $consultData[$key];
  124.         if (!isset($consSchedule['localWt'])) {
  125.             $this->eventDispatcher->dispatch(new GeneralErrorEvent(new Exception("Портал не вернул параметр localWt в методе API получения графика консультантов для конс_страна: '$key'. Подставляем по умолчанию с 10 до 18")));
  126.         }
  127.         $this->modifyWorkTimeIfNeed($consLogin$country$initialConsultData$consSchedule);
  128.         /*
  129.          * Вс - 0-й день, пн - 1-й, вт - 2-й, ...
  130.          */
  131.         $workDaysNumbers $consSchedule['dayOfWeek'];
  132.         $workDaysString $this->getWorkDaysStringByWorkDaysArray($workDaysNumbers$locale);
  133.         /*
  134.          * wt: время по портальному серверу (на нем используется часовой пояс МСК)
  135.          * timezone: часовой пояс по стране клиента
  136.          * localWt: время по стране клиента
  137.          * wtTimezone: часовой пояс по серверу (на нем используется часовой пояс МСК)
  138.          */
  139.         //Отображаем в приветственном сообщении время и часовой пояс по стране клиента.
  140.         return [
  141.             'work_hours_string' => $consSchedule['localWt'] ?? 'work_hours_not_defined',
  142.             'work_days_string'  => $workDaysString,
  143.             'timezone_string'   => $consSchedule['timezone'] ?? 'timezone_not_defined',
  144.         ];
  145.     }
  146.     private function getWorkDaysStringByWorkDaysArray(array $workDaysArraystring $locale): string
  147.     {
  148.         $workDaysArrayStrings = [];
  149.         foreach ($workDaysArray as $workDayNumber) {
  150.             $workDaysArrayStrings[] = $this->translatorWrapper->translate("weekday.$workDayNumber.short"$locale);
  151.         }
  152.         return implode(', '$workDaysArrayStrings);
  153.     }
  154.     protected function modifyConsultDataArrayContent(string $consLoginstring $country, ?array $consultData): array
  155.     {
  156.         $initialConsultData $consultData;
  157.         foreach ($consultData as &$val) {
  158.             if (is_array($val['country'])) {
  159.                 $subArr $val['country'];
  160.                 $val['country'] = $subArr[0] ?? 'en';
  161.             }
  162.             if ('en2' === $val['country']) {
  163.                 $val['country'] = 'en';
  164.             }
  165.             $consultData[($val['login'] ?? 'no_login') . '_' $val['country'] ?? 'no_country'] = $val;
  166.         }
  167.         $key $consLogin '_' $country;
  168.         return [$initialConsultData$consultData$key];
  169.     }
  170.     protected function modifyCountry(string $countrystring $countryByIp): string
  171.     {
  172.         if ('en' === $country) {
  173.             $country $countryByIp;
  174.             if ('en' === $country) {
  175.                 $country 'gb';
  176.             }
  177.         }
  178.         return $country;
  179.     }
  180.     /**
  181.      * Объединяет графики работы консов по одинаковой стране, если их график работы пн - пт, а также время конца одного совпадает со временем начала другого.
  182.      *
  183.      * @param $consSchedule
  184.      */
  185.     private function modifyWorkTimeIfNeed(string $consLoginstring $country, array $initialConsultData, &$consSchedule)
  186.     {
  187.         //Если график конса не пн-пт - ничего не меняем
  188.         if (!$this->consWorkFromMondayTillFriday($consSchedule)) {
  189.             return;
  190.         }
  191.         $consultantsWithTheSameCountryAndMondayTillFridayWorkingDays = [$consSchedule];
  192.         foreach ($initialConsultData as $element) {
  193.             if ($element['login'] !== $consLogin && $element['country'] === $country && $this->consWorkFromMondayTillFriday($element)) {
  194.                 $consultantsWithTheSameCountryAndMondayTillFridayWorkingDays[] = $element;
  195.             }
  196.         }
  197.         $earliestCons $this->getEarliest($consultantsWithTheSameCountryAndMondayTillFridayWorkingDays);
  198.         foreach ($consultantsWithTheSameCountryAndMondayTillFridayWorkingDays as $element) {
  199.             if ($element === $earliestCons) {
  200.                 continue;
  201.             }
  202.             if (substr($earliestCons['localWt'], 65) === substr($element['localWt'], 05)) {
  203.                 $consSchedule['localWt'] = substr($earliestCons['localWt'], 05) . '-' substr($element['localWt'], 65);
  204.                 $consSchedule['wt'] = substr($earliestCons['wt'], 05) . '-' substr($element['wt'], 65);
  205.                 return;
  206.             }
  207.         }
  208.     }
  209.     private function consWorkFromMondayTillFriday(array $consSchedule): bool
  210.     {
  211.         return empty(array_diff($consSchedule['dayOfWeek'], [12345])) && empty(array_diff([12345], $consSchedule['dayOfWeek']));
  212.     }
  213.     private function getEarliest($consultantsWithTheSameCountryAndMondayTillFridayWorkingDays)
  214.     {
  215.         $minElement $consultantsWithTheSameCountryAndMondayTillFridayWorkingDays[0];
  216.         $min = ['localWt'] ?? '02:00'//если портал не прислал (что неправильно) - ставим дефолтное значение
  217.         foreach ($consultantsWithTheSameCountryAndMondayTillFridayWorkingDays as $element) {
  218.             if ($element['localWt'] < $min) {
  219.                 $minElement $element;
  220.                 $min $element['localWt'];
  221.             }
  222.         }
  223.         return $minElement;
  224.     }
  225.     private function selfUnion(array $consultantsSchedule): array
  226.     {
  227.         if (false) {
  228.             $consultantsSchedule $this->getStubArray();
  229.         }
  230.         $resultArray = [];
  231.         foreach ($consultantsSchedule['result']['consultData'] ?? [] as $sourceRecord) {
  232.             if ($resultArrayRecordWithTheSameLoginAndCountry $this->getRecordFromResultArrayWithTheSameLoginAndCountry($resultArray,
  233.                 $sourceRecord)) {
  234.                 $this->mergeSourceRecordToResultArray($resultArray$resultArrayRecordWithTheSameLoginAndCountry$sourceRecord);
  235.             } else {
  236.                 $resultArray[] = $sourceRecord;
  237.             }
  238.         }
  239.         $consultantsSchedule['result']['consultData'] = $resultArray;
  240.         return $consultantsSchedule;
  241.     }
  242.     private function getRecordFromResultArrayWithTheSameLoginAndCountry(array $resultArray, array $sourceRecord): ?array
  243.     {
  244.         foreach ($resultArray as $resultArrayRecord) {
  245.             if ($resultArrayRecord['login'] === $sourceRecord['login'] && $resultArrayRecord['country'] === $sourceRecord['country']) {
  246.                 return $resultArrayRecord;
  247.             }
  248.         }
  249.         return null;
  250.     }
  251.     private function mergeSourceRecordToResultArray(array &$resultArray, array $oldRecord, array $newRecord)
  252.     {
  253.         $key array_search($oldRecord$resultArray);
  254.         $resultArray[$key] = $this->mergeTwoConsRecords($oldRecord$newRecord);
  255.     }
  256.     private function getStubArray(): array
  257.     {
  258.         return [
  259.             'success' => true,
  260.             'result'  => [
  261.                 'consultData' => [
  262.                     0  => [
  263.                         'wt'         => '09:00-14:30',
  264.                         'login'      => 'dfilinkova',
  265.                         'country'    => 'de',
  266.                         'timezone'   => 'Europe/Berlin',
  267.                         'onFreeTime' => false,
  268.                         'dayOfWeek'  => [
  269.                             => 1,
  270.                             => 2,
  271.                             => 3,
  272.                             => 4,
  273.                             => 5,
  274.                         ],
  275.                         'localWt'    => '08:00-13:30',
  276.                         'wtTimezone' => 'Europe/Moscow',
  277.                     ],
  278.                     1  => [
  279.                         'wt'         => '09:00-14:30',
  280.                         'login'      => 'dfilinkova',
  281.                         'country'    => 'at',
  282.                         'timezone'   => 'Europe/Vienna',
  283.                         'onFreeTime' => false,
  284.                         'dayOfWeek'  => [
  285.                             => 1,
  286.                             => 2,
  287.                             => 3,
  288.                             => 4,
  289.                             => 5,
  290.                         ],
  291.                         'localWt'    => '08:00-13:30',
  292.                         'wtTimezone' => 'Europe/Moscow',
  293.                     ],
  294.                     2  => [
  295.                         'wt'         => '14:30-20:00',
  296.                         'login'      => 'akroyshner',
  297.                         'country'    => 'de',
  298.                         'timezone'   => 'Europe/Berlin',
  299.                         'onFreeTime' => false,
  300.                         'dayOfWeek'  => [
  301.                             => 1,
  302.                             => 2,
  303.                             => 3,
  304.                             => 4,
  305.                             => 5,
  306.                         ],
  307.                         'localWt'    => '13:30-19:00',
  308.                         'wtTimezone' => 'Europe/Moscow',
  309.                     ],
  310.                     3  => [
  311.                         'wt'         => '14:30-20:00',
  312.                         'login'      => 'akroyshner',
  313.                         'country'    => 'at',
  314.                         'timezone'   => 'Europe/Vienna',
  315.                         'onFreeTime' => false,
  316.                         'dayOfWeek'  => [
  317.                             => 1,
  318.                             => 2,
  319.                             => 3,
  320.                             => 4,
  321.                             => 5,
  322.                         ],
  323.                         'localWt'    => '13:30-19:00',
  324.                         'wtTimezone' => 'Europe/Moscow',
  325.                     ],
  326.                     4  => [
  327.                         'wt'         => '16:00-01:00',
  328.                         'login'      => 'iyarosh',
  329.                         'country'    => 'us',
  330.                         'timezone'   => 'America/New_York',
  331.                         'onFreeTime' => false,
  332.                         'dayOfWeek'  => [
  333.                             => 1,
  334.                             => 2,
  335.                             => 3,
  336.                             => 4,
  337.                             => 5,
  338.                         ],
  339.                         'localWt'    => '09:00-18:00',
  340.                         'wtTimezone' => 'Europe/Moscow',
  341.                     ],
  342.                     5  => [
  343.                         'wt'         => '16:00-01:00',
  344.                         'login'      => 'iyarosh',
  345.                         'country'    => 'ca',
  346.                         'timezone'   => 'America/Toronto',
  347.                         'onFreeTime' => false,
  348.                         'dayOfWeek'  => [
  349.                             => 1,
  350.                             => 2,
  351.                             => 3,
  352.                             => 4,
  353.                             => 5,
  354.                         ],
  355.                         'localWt'    => '09:00-18:00',
  356.                         'wtTimezone' => 'Europe/Moscow',
  357.                     ],
  358.                     6  => [
  359.                         'wt'         => '11:00-19:00',
  360.                         'login'      => 'akuznetsova',
  361.                         'country'    => 'es',
  362.                         'timezone'   => 'Europe/Madrid',
  363.                         'onFreeTime' => false,
  364.                         'dayOfWeek'  => [
  365.                             => 1,
  366.                             => 2,
  367.                             => 3,
  368.                             => 4,
  369.                             => 5,
  370.                         ],
  371.                         'localWt'    => '10:00-18:00',
  372.                         'wtTimezone' => 'Europe/Moscow',
  373.                     ],
  374.                     7  => [
  375.                         'wt'         => '14:30-19:00',
  376.                         'login'      => 'mshevchuk4618',
  377.                         'country'    => 'fr',
  378.                         'timezone'   => 'Europe/Paris',
  379.                         'onFreeTime' => false,
  380.                         'dayOfWeek'  => [
  381.                             => 1,
  382.                             => 2,
  383.                             => 3,
  384.                             => 4,
  385.                             => 5,
  386.                         ],
  387.                         'localWt'    => '13:30-18:00',
  388.                         'wtTimezone' => 'Europe/Moscow',
  389.                     ],
  390.                     8  => [
  391.                         'wt'         => '09:00-18:00',
  392.                         'login'      => 'ylipezin',
  393.                         'country'    => 'nl',
  394.                         'timezone'   => 'Europe/Amsterdam',
  395.                         'onFreeTime' => false,
  396.                         'dayOfWeek'  => [
  397.                             => 1,
  398.                             => 2,
  399.                             => 3,
  400.                             => 4,
  401.                             => 5,
  402.                         ],
  403.                         'localWt'    => '08:00-17:00',
  404.                         'wtTimezone' => 'Europe/Moscow',
  405.                     ],
  406.                     9  => [
  407.                         'wt'         => '10:00-19:00',
  408.                         'login'      => 'akadurkina17519',
  409.                         'country'    => 'en',
  410.                         'timezone'   => 'Europe/Tallinn',
  411.                         'onFreeTime' => false,
  412.                         'dayOfWeek'  => [
  413.                             => 1,
  414.                             => 2,
  415.                             => 3,
  416.                             => 4,
  417.                             => 5,
  418.                         ],
  419.                         'localWt'    => '10:00-19:00',
  420.                         'wtTimezone' => 'Europe/Moscow',
  421.                     ],
  422.                     10 => [
  423.                         'wt'         => '10:00-19:00',
  424.                         'login'      => 'akadurkina17519',
  425.                         'country'    => 'en2',
  426.                         'timezone'   => 'Europe/Tallinn',
  427.                         'onFreeTime' => false,
  428.                         'dayOfWeek'  => [
  429.                             => 1,
  430.                             => 2,
  431.                             => 3,
  432.                             => 4,
  433.                             => 5,
  434.                         ],
  435.                         'localWt'    => '10:00-19:00',
  436.                         'wtTimezone' => 'Europe/Moscow',
  437.                     ],
  438.                     11 => [
  439.                         'wt'         => '10:00-19:00',
  440.                         'login'      => 'akadurkina17519',
  441.                         'country'    => 'dk',
  442.                         'timezone'   => 'Europe/Copenhagen',
  443.                         'onFreeTime' => false,
  444.                         'dayOfWeek'  => [
  445.                             => 1,
  446.                             => 2,
  447.                             => 3,
  448.                             => 4,
  449.                             => 5,
  450.                         ],
  451.                         'localWt'    => '09:00-18:00',
  452.                         'wtTimezone' => 'Europe/Moscow',
  453.                     ],
  454.                     12 => [
  455.                         'wt'         => '10:00-19:00',
  456.                         'login'      => 'akadurkina17519',
  457.                         'country'    => 'lv',
  458.                         'timezone'   => 'Europe/Riga',
  459.                         'onFreeTime' => false,
  460.                         'dayOfWeek'  => [
  461.                             => 1,
  462.                             => 2,
  463.                             => 3,
  464.                             => 4,
  465.                             => 5,
  466.                         ],
  467.                         'localWt'    => '10:00-19:00',
  468.                         'wtTimezone' => 'Europe/Moscow',
  469.                     ],
  470.                     13 => [
  471.                         'wt'         => '09:00-18:00',
  472.                         'login'      => 'akadurkina17519',
  473.                         'country'    => 'lt',
  474.                         'timezone'   => 'Europe/Vilnius',
  475.                         'onFreeTime' => false,
  476.                         'dayOfWeek'  => [
  477.                             => 1,
  478.                             => 2,
  479.                             => 3,
  480.                             => 4,
  481.                             => 5,
  482.                         ],
  483.                         'localWt'    => '09:00-18:00',
  484.                         'wtTimezone' => 'Europe/Moscow',
  485.                     ],
  486.                     14 => [
  487.                         'wt'         => '10:00-19:00',
  488.                         'login'      => 'akadurkina17519',
  489.                         'country'    => 'se',
  490.                         'timezone'   => 'Europe/Stockholm',
  491.                         'onFreeTime' => false,
  492.                         'dayOfWeek'  => [
  493.                             => 1,
  494.                             => 2,
  495.                             => 3,
  496.                             => 4,
  497.                             => 5,
  498.                         ],
  499.                         'localWt'    => '09:00-18:00',
  500.                         'wtTimezone' => 'Europe/Moscow',
  501.                     ],
  502.                     15 => [
  503.                         'wt'         => '10:00-19:00',
  504.                         'login'      => 'akadurkina17519',
  505.                         'country'    => 'ee',
  506.                         'timezone'   => 'Europe/Tallinn',
  507.                         'onFreeTime' => false,
  508.                         'dayOfWeek'  => [
  509.                             => 1,
  510.                             => 2,
  511.                             => 3,
  512.                             => 4,
  513.                             => 5,
  514.                         ],
  515.                         'localWt'    => '10:00-19:00',
  516.                         'wtTimezone' => 'Europe/Moscow',
  517.                     ],
  518.                     16 => [
  519.                         'wt'         => '10:00-19:00',
  520.                         'login'      => 'akadurkina17519',
  521.                         'country'    => 'bg',
  522.                         'timezone'   => 'Europe/Sofia',
  523.                         'onFreeTime' => false,
  524.                         'dayOfWeek'  => [
  525.                             => 1,
  526.                             => 2,
  527.                             => 3,
  528.                             => 4,
  529.                             => 5,
  530.                         ],
  531.                         'localWt'    => '10:00-19:00',
  532.                         'wtTimezone' => 'Europe/Moscow',
  533.                     ],
  534.                     17 => [
  535.                         'wt'         => '10:00-19:00',
  536.                         'login'      => 'akadurkina17519',
  537.                         'country'    => 'hu',
  538.                         'timezone'   => 'Europe/Budapest',
  539.                         'onFreeTime' => false,
  540.                         'dayOfWeek'  => [
  541.                             => 1,
  542.                             => 2,
  543.                             => 3,
  544.                             => 4,
  545.                             => 5,
  546.                         ],
  547.                         'localWt'    => '09:00-18:00',
  548.                         'wtTimezone' => 'Europe/Moscow',
  549.                     ],
  550.                     18 => [
  551.                         'wt'         => '10:00-19:00',
  552.                         'login'      => 'akadurkina17519',
  553.                         'country'    => 'gr',
  554.                         'timezone'   => 'Europe/Athens',
  555.                         'onFreeTime' => false,
  556.                         'dayOfWeek'  => [
  557.                             => 1,
  558.                             => 2,
  559.                             => 3,
  560.                             => 4,
  561.                             => 5,
  562.                         ],
  563.                         'localWt'    => '10:00-19:00',
  564.                         'wtTimezone' => 'Europe/Moscow',
  565.                     ],
  566.                     19 => [
  567.                         'wt'         => '14:30-19:00',
  568.                         'login'      => 'mshevchuk4618',
  569.                         'country'    => 'lu',
  570.                         'timezone'   => 'Europe/Luxembourg',
  571.                         'onFreeTime' => false,
  572.                         'dayOfWeek'  => [
  573.                             => 1,
  574.                             => 2,
  575.                             => 3,
  576.                             => 4,
  577.                             => 5,
  578.                         ],
  579.                         'localWt'    => '13:30-18:00',
  580.                         'wtTimezone' => 'Europe/Moscow',
  581.                     ],
  582.                     20 => [
  583.                         'wt'         => '10:00-19:00',
  584.                         'login'      => 'akadurkina17519',
  585.                         'country'    => 'mt',
  586.                         'timezone'   => 'Europe/Malta',
  587.                         'onFreeTime' => false,
  588.                         'dayOfWeek'  => [
  589.                             => 1,
  590.                             => 2,
  591.                             => 3,
  592.                             => 4,
  593.                             => 5,
  594.                         ],
  595.                         'localWt'    => '09:00-18:00',
  596.                         'wtTimezone' => 'Europe/Moscow',
  597.                     ],
  598.                     21 => [
  599.                         'wt'         => '10:00-19:00',
  600.                         'login'      => 'akadurkina17519',
  601.                         'country'    => 'cy',
  602.                         'timezone'   => 'Asia/Nicosia',
  603.                         'onFreeTime' => false,
  604.                         'dayOfWeek'  => [
  605.                             => 1,
  606.                             => 2,
  607.                             => 3,
  608.                             => 4,
  609.                             => 5,
  610.                         ],
  611.                         'localWt'    => '10:00-19:00',
  612.                         'wtTimezone' => 'Europe/Moscow',
  613.                     ],
  614.                     22 => [
  615.                         'wt'         => '10:00-19:00',
  616.                         'login'      => 'akadurkina17519',
  617.                         'country'    => 'no',
  618.                         'timezone'   => 'Europe/Oslo',
  619.                         'onFreeTime' => false,
  620.                         'dayOfWeek'  => [
  621.                             => 1,
  622.                             => 2,
  623.                             => 3,
  624.                             => 4,
  625.                             => 5,
  626.                         ],
  627.                         'localWt'    => '09:00-18:00',
  628.                         'wtTimezone' => 'Europe/Moscow',
  629.                     ],
  630.                     23 => [
  631.                         'wt'         => '13:00-22:00',
  632.                         'login'      => 'akadurkina17519',
  633.                         'country'    => 'pt',
  634.                         'timezone'   => 'Europe/Lisbon',
  635.                         'onFreeTime' => false,
  636.                         'dayOfWeek'  => [
  637.                             => 1,
  638.                             => 2,
  639.                             => 3,
  640.                             => 4,
  641.                             => 5,
  642.                         ],
  643.                         'localWt'    => '11:00-20:00',
  644.                         'wtTimezone' => 'Europe/Moscow',
  645.                     ],
  646.                     24 => [
  647.                         'wt'         => '10:00-19:00',
  648.                         'login'      => 'akadurkina17519',
  649.                         'country'    => 'ro',
  650.                         'timezone'   => 'Europe/Bucharest',
  651.                         'onFreeTime' => false,
  652.                         'dayOfWeek'  => [
  653.                             => 1,
  654.                             => 2,
  655.                             => 3,
  656.                             => 4,
  657.                             => 5,
  658.                         ],
  659.                         'localWt'    => '10:00-19:00',
  660.                         'wtTimezone' => 'Europe/Moscow',
  661.                     ],
  662.                     25 => [
  663.                         'wt'         => '10:00-19:00',
  664.                         'login'      => 'akadurkina17519',
  665.                         'country'    => 'sk',
  666.                         'timezone'   => 'Europe/Bratislava',
  667.                         'onFreeTime' => false,
  668.                         'dayOfWeek'  => [
  669.                             => 1,
  670.                             => 2,
  671.                             => 3,
  672.                             => 4,
  673.                             => 5,
  674.                         ],
  675.                         'localWt'    => '09:00-18:00',
  676.                         'wtTimezone' => 'Europe/Moscow',
  677.                     ],
  678.                     26 => [
  679.                         'wt'         => '11:00-20:00',
  680.                         'login'      => 'akadurkina17519',
  681.                         'country'    => 'si',
  682.                         'timezone'   => 'Europe/Ljubljana',
  683.                         'onFreeTime' => false,
  684.                         'dayOfWeek'  => [
  685.                             => 1,
  686.                             => 2,
  687.                             => 3,
  688.                             => 4,
  689.                             => 5,
  690.                         ],
  691.                         'localWt'    => '10:00-19:00',
  692.                         'wtTimezone' => 'Europe/Moscow',
  693.                     ],
  694.                     27 => [
  695.                         'wt'         => '10:00-19:00',
  696.                         'login'      => 'akadurkina17519',
  697.                         'country'    => 'cz',
  698.                         'timezone'   => 'Europe/Prague',
  699.                         'onFreeTime' => false,
  700.                         'dayOfWeek'  => [
  701.                             => 1,
  702.                             => 2,
  703.                             => 3,
  704.                             => 4,
  705.                             => 5,
  706.                         ],
  707.                         'localWt'    => '09:00-18:00',
  708.                         'wtTimezone' => 'Europe/Moscow',
  709.                     ],
  710.                     28 => [
  711.                         'wt'         => '09:00-18:00',
  712.                         'login'      => 'ylipezin',
  713.                         'country'    => 'be',
  714.                         'timezone'   => 'Europe/Brussels',
  715.                         'onFreeTime' => false,
  716.                         'dayOfWeek'  => [
  717.                             => 1,
  718.                             => 2,
  719.                             => 3,
  720.                             => 4,
  721.                             => 5,
  722.                         ],
  723.                         'localWt'    => '08:00-17:00',
  724.                         'wtTimezone' => 'Europe/Moscow',
  725.                     ],
  726.                     29 => [
  727.                         'wt'         => '11:00-20:00',
  728.                         'login'      => 'tkonyukhova',
  729.                         'country'    => 'ie',
  730.                         'timezone'   => 'Europe/Dublin',
  731.                         'onFreeTime' => false,
  732.                         'dayOfWeek'  => [
  733.                             => 1,
  734.                             => 2,
  735.                             => 3,
  736.                             => 4,
  737.                             => 5,
  738.                         ],
  739.                         'localWt'    => '09:00-18:00',
  740.                         'wtTimezone' => 'Europe/Moscow',
  741.                     ],
  742.                     30 => [
  743.                         'wt'         => '11:00-20:00',
  744.                         'login'      => 'tkonyukhova',
  745.                         'country'    => 'gb',
  746.                         'timezone'   => 'Europe/London',
  747.                         'onFreeTime' => false,
  748.                         'dayOfWeek'  => [
  749.                             => 1,
  750.                             => 2,
  751.                             => 3,
  752.                             => 4,
  753.                             => 5,
  754.                         ],
  755.                         'localWt'    => '09:00-18:00',
  756.                         'wtTimezone' => 'Europe/Moscow',
  757.                     ],
  758.                     31 => [
  759.                         'wt'         => '09:00-14:30',
  760.                         'login'      => 'dfilinkova',
  761.                         'country'    => 'ch',
  762.                         'timezone'   => 'Europe/Zurich',
  763.                         'onFreeTime' => false,
  764.                         'dayOfWeek'  => [
  765.                             => 1,
  766.                             => 2,
  767.                             => 3,
  768.                             => 4,
  769.                             => 5,
  770.                         ],
  771.                         'localWt'    => '08:00-13:30',
  772.                         'wtTimezone' => 'Europe/Moscow',
  773.                     ],
  774.                     32 => [
  775.                         'wt'         => '14:30-20:00',
  776.                         'login'      => 'akroyshner',
  777.                         'country'    => 'ch',
  778.                         'timezone'   => 'Europe/Zurich',
  779.                         'onFreeTime' => false,
  780.                         'dayOfWeek'  => [
  781.                             => 1,
  782.                             => 2,
  783.                             => 3,
  784.                             => 4,
  785.                             => 5,
  786.                         ],
  787.                         'localWt'    => '13:30-19:00',
  788.                         'wtTimezone' => 'Europe/Moscow',
  789.                     ],
  790.                     33 => [
  791.                         'wt'         => '10:00-19:00',
  792.                         'login'      => 'akadurkina17519',
  793.                         'country'    => 'fi',
  794.                         'timezone'   => 'Europe/Helsinki',
  795.                         'onFreeTime' => false,
  796.                         'dayOfWeek'  => [
  797.                             => 1,
  798.                             => 2,
  799.                             => 3,
  800.                             => 4,
  801.                             => 5,
  802.                         ],
  803.                         'localWt'    => '10:00-19:00',
  804.                         'wtTimezone' => 'Europe/Moscow',
  805.                     ],
  806.                     34 => [
  807.                         'wt'         => '10:00-19:00',
  808.                         'login'      => 'akadurkina17519',
  809.                         'country'    => 'pl',
  810.                         'timezone'   => 'Europe/Warsaw',
  811.                         'onFreeTime' => false,
  812.                         'dayOfWeek'  => [
  813.                             => 1,
  814.                             => 2,
  815.                             => 3,
  816.                             => 4,
  817.                             => 5,
  818.                         ],
  819.                         'localWt'    => '09:00-18:00',
  820.                         'wtTimezone' => 'Europe/Moscow',
  821.                     ],
  822.                     35 => [
  823.                         'wt'         => '07:00-21:00',
  824.                         'login'      => 'vpenkov6618',
  825.                         'country'    => 'ru',
  826.                         'timezone'   => 'Europe/Moscow',
  827.                         'onFreeTime' => false,
  828.                         'dayOfWeek'  => [
  829.                             => 1,
  830.                             => 2,
  831.                             => 3,
  832.                             => 4,
  833.                             => 5,
  834.                         ],
  835.                         'localWt'    => '07:00-21:00',
  836.                         'wtTimezone' => 'Europe/Moscow',
  837.                     ],
  838.                     36 => [
  839.                         'wt'         => '07:00-00:00',
  840.                         'login'      => 'atarasov',
  841.                         'country'    => 'ru',
  842.                         'timezone'   => 'Europe/Moscow',
  843.                         'onFreeTime' => false,
  844.                         'dayOfWeek'  => [
  845.                             => 0,
  846.                             => 6,
  847.                         ],
  848.                         'localWt'    => '07:00-00:00',
  849.                         'wtTimezone' => 'Europe/Moscow',
  850.                     ],
  851.                     37 => [
  852.                         'wt'         => '10:00-14:30',
  853.                         'login'      => 'mshevchuk4618',
  854.                         'country'    => 'fr',
  855.                         'timezone'   => 'Europe/Paris',
  856.                         'onFreeTime' => false,
  857.                         'dayOfWeek'  => [
  858.                             => 1,
  859.                             => 2,
  860.                             => 3,
  861.                             => 4,
  862.                             => 5,
  863.                         ],
  864.                         'localWt'    => '09:00-13:30',
  865.                         'wtTimezone' => 'Europe/Moscow',
  866.                     ],
  867.                     38 => [
  868.                         'wt'         => '10:00-14:30',
  869.                         'login'      => 'mshevchuk4618',
  870.                         'country'    => 'lu',
  871.                         'timezone'   => 'Europe/Luxembourg',
  872.                         'onFreeTime' => false,
  873.                         'dayOfWeek'  => [
  874.                             => 1,
  875.                             => 2,
  876.                             => 3,
  877.                             => 4,
  878.                             => 5,
  879.                         ],
  880.                         'localWt'    => '09:00-13:30',
  881.                         'wtTimezone' => 'Europe/Moscow',
  882.                     ],
  883.                     39 => [
  884.                         'wt'         => '10:00-19:00',
  885.                         'login'      => 'akadurkina17519',
  886.                         'country'    => 'hr',
  887.                         'timezone'   => 'Europe/Zagreb',
  888.                         'onFreeTime' => false,
  889.                         'dayOfWeek'  => [
  890.                             => 1,
  891.                             => 2,
  892.                             => 3,
  893.                             => 4,
  894.                             => 5,
  895.                         ],
  896.                         'localWt'    => '09:00-18:00',
  897.                         'wtTimezone' => 'Europe/Moscow',
  898.                     ],
  899.                     40 => [
  900.                         'wt'         => '10:00-19:00',
  901.                         'login'      => 'nostanina25719',
  902.                         'country'    => 'it',
  903.                         'timezone'   => 'Europe/Rome',
  904.                         'onFreeTime' => false,
  905.                         'dayOfWeek'  => [
  906.                             => 1,
  907.                             => 2,
  908.                             => 3,
  909.                             => 4,
  910.                             => 5,
  911.                         ],
  912.                         'localWt'    => '09:00-18:00',
  913.                         'wtTimezone' => 'Europe/Moscow',
  914.                     ],
  915.                 ],
  916.             ],
  917.         ];
  918.     }
  919.     private function mergeTwoConsRecords(array $record1, array $record2): array
  920.     {
  921.         $localWtBeginOfRecord1 substr($record1['localWt'], 05);
  922.         $localWtEndOfRecord1 substr($record1['localWt'], 65);
  923.         $localWtBeginOfRecord2 substr($record2['localWt'], 05);
  924.         $localWtEndOfRecord2 substr($record2['localWt'], 65);
  925.         if ($localWtBeginOfRecord1 $localWtBeginOfRecord2) {
  926.             if ($localWtEndOfRecord1 === $localWtBeginOfRecord2) {
  927.                 $record1['localWt'] = $localWtBeginOfRecord1 '-' $localWtEndOfRecord2;
  928.                 $record1['wt'] = substr($record1['wt'], 05) . '-' substr($record2['wt'], 65);
  929.             }
  930.             return $record1;
  931.         }
  932.         if ($localWtEndOfRecord2 === $localWtBeginOfRecord1) {
  933.             $record2['localWt'] = $localWtBeginOfRecord2 '-' $localWtEndOfRecord1;
  934.             $record2['wt'] = substr($record2['wt'], 05) . '-' substr($record1['wt'], 65);
  935.         }
  936.         return $record2;
  937.     }
  938. }