Use streaming parser in schedules
This commit is contained in:
parent
5fb80224ce
commit
f64855e454
@ -13,5 +13,5 @@ APP_SECRET=1bdf86cdc78fba654e4f2c309c6bbdbd
|
|||||||
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||||
# Configure your db driver and server_version in config/packages/doctrine.yaml
|
# Configure your db driver and server_version in config/packages/doctrine.yaml
|
||||||
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
|
DATABASE_URL=sqlite:///%kernel.project_dir%/var/app.db
|
||||||
###< doctrine/doctrine-bundle ###
|
###< doctrine/doctrine-bundle ###
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
|
"cerbero/json-objects": "^1.1",
|
||||||
"doctrine/doctrine-cache-bundle": "^1.4",
|
"doctrine/doctrine-cache-bundle": "^1.4",
|
||||||
"jms/serializer-bundle": "^3.5",
|
"jms/serializer-bundle": "^3.5",
|
||||||
"nelmio/api-doc-bundle": "^3.5",
|
"nelmio/api-doc-bundle": "^3.5",
|
||||||
|
178
composer.lock
generated
178
composer.lock
generated
@ -4,8 +4,66 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "ea09297f32ae7bb1a4392cb514b0d0b2",
|
"content-hash": "8efb4e4271b8598760e37b9b33d9a14f",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "cerbero/json-objects",
|
||||||
|
"version": "v1.1.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cerbero90/json-objects.git",
|
||||||
|
"reference": "21eac219bb20ca80318fec88821217d7417ee09a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cerbero90/json-objects/zipball/21eac219bb20ca80318fec88821217d7417ee09a",
|
||||||
|
"reference": "21eac219bb20ca80318fec88821217d7417ee09a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "~7.1",
|
||||||
|
"psr/http-message": "^1.0",
|
||||||
|
"salsify/json-streaming-parser": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.2",
|
||||||
|
"phpunit/phpunit": ">=7.0",
|
||||||
|
"squizlabs/php_codesniffer": "^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Cerbero\\JsonObjects\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrea Marco Sartori",
|
||||||
|
"email": "andrea.marco.sartori@gmail.com",
|
||||||
|
"homepage": "https://github.com/cerbero90",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Extract objects from large JSON files, endpoints or streams while saving memory.",
|
||||||
|
"homepage": "https://github.com/cerbero90/json-objects",
|
||||||
|
"keywords": [
|
||||||
|
"cerbero",
|
||||||
|
"json",
|
||||||
|
"json-objects",
|
||||||
|
"parser",
|
||||||
|
"stream"
|
||||||
|
],
|
||||||
|
"time": "2019-04-26T13:04:36+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
"version": "v1.8.0",
|
"version": "v1.8.0",
|
||||||
@ -2964,6 +3022,56 @@
|
|||||||
],
|
],
|
||||||
"time": "2017-02-14T16:28:37+00:00"
|
"time": "2017-02-14T16:28:37+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-message",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-message.git",
|
||||||
|
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||||
|
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "http://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for HTTP messages",
|
||||||
|
"homepage": "https://github.com/php-fig/http-message",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"http-message",
|
||||||
|
"psr",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"time": "2016-08-06T14:39:51+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -3011,6 +3119,74 @@
|
|||||||
],
|
],
|
||||||
"time": "2019-11-01T11:05:21+00:00"
|
"time": "2019-11-01T11:05:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "salsify/json-streaming-parser",
|
||||||
|
"version": "v8.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/salsify/jsonstreamingparser.git",
|
||||||
|
"reference": "0e5b5cb12611fe5376af653b360e12e8c6c6f3bd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/salsify/jsonstreamingparser/zipball/0e5b5cb12611fe5376af653b360e12e8c6c6f3bd",
|
||||||
|
"reference": "0e5b5cb12611fe5376af653b360e12e8c6c6f3bd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"satooshi/php-coveralls": "~2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "8.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"JsonStreamingParser\\": "src",
|
||||||
|
"JsonStreamingParser\\Test\\": "tests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Rob Gonzalez",
|
||||||
|
"email": "rob@salsify.com",
|
||||||
|
"homepage": "http://salsify.com/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Maxim Gnatenko",
|
||||||
|
"email": "mgnatenko@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Max Grigorian",
|
||||||
|
"email": "maxakawizard@gmail.com",
|
||||||
|
"homepage": "http://wizardcat.com/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ThePanz",
|
||||||
|
"email": "thepanz@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A streaming parser for JSON in PHP.",
|
||||||
|
"homepage": "https://github.com/salsify/jsonstreamingparser",
|
||||||
|
"keywords": [
|
||||||
|
"json",
|
||||||
|
"parser",
|
||||||
|
"streaming"
|
||||||
|
],
|
||||||
|
"time": "2019-10-13T13:40:17+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "sensio/framework-extra-bundle",
|
"name": "sensio/framework-extra-bundle",
|
||||||
"version": "v5.5.3",
|
"version": "v5.5.3",
|
||||||
|
@ -5,8 +5,8 @@ doctrine:
|
|||||||
dbal:
|
dbal:
|
||||||
driver: 'pdo_sqlite'
|
driver: 'pdo_sqlite'
|
||||||
url: '%env(resolve:DATABASE_URL)%'
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
logging: false
|
logging: true
|
||||||
profiling: false
|
profiling: true
|
||||||
|
|
||||||
orm:
|
orm:
|
||||||
auto_generate_proxy_classes: '%kernel.debug%'
|
auto_generate_proxy_classes: '%kernel.debug%'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: '2'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
@ -11,6 +11,9 @@ services:
|
|||||||
|
|
||||||
php:
|
php:
|
||||||
build: docker/php
|
build: docker/php
|
||||||
|
mem_limit: 2g
|
||||||
|
env_file:
|
||||||
|
- ./docker/php/.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www:cached
|
- ./:/var/www:cached
|
||||||
- ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf
|
- ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf
|
||||||
|
2
docker/php/.env
Normal file
2
docker/php/.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
XDEBUG_CONFIG=remote_host=172.17.0.1 remote_port=9001
|
||||||
|
PHP_IDE_CONFIG=serverName=czydojade
|
@ -7,6 +7,8 @@ RUN docker-php-ext-install zip
|
|||||||
|
|
||||||
RUN pecl install xdebug-2.9.0 && docker-php-ext-enable xdebug
|
RUN pecl install xdebug-2.9.0 && docker-php-ext-enable xdebug
|
||||||
|
|
||||||
|
RUN echo "xdebug.remote_enable = 1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;
|
||||||
|
|
||||||
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||||
RUN php composer-setup.php
|
RUN php composer-setup.php
|
||||||
RUN php -r "unlink('composer-setup.php');"
|
RUN php -r "unlink('composer-setup.php');"
|
||||||
@ -16,3 +18,5 @@ RUN chmod +x /usr/local/bin/composer
|
|||||||
RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
|
RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
|
||||||
|
|
||||||
WORKDIR /var/www
|
WORKDIR /var/www
|
||||||
|
|
||||||
|
EXPOSE 9001
|
||||||
|
@ -7,14 +7,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="departure__time">
|
<div class="departure__time">
|
||||||
<span class="departure__scheduled" v-if="departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm')">
|
<fa :icon="['far', 'clock']" v-if="!departure.estimated" title="Czas rozkładowy, nie uwzględniający aktualnej sytuacji komunikacyjnej."/>
|
||||||
|
<span :class="[ 'departure__scheduled', departure.estimated && departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm') && 'departure__scheduled--delayed']">
|
||||||
{{ departure.scheduled.format('HH:mm') }}
|
{{ departure.scheduled.format('HH:mm') }}
|
||||||
</span>
|
</span>
|
||||||
<span class="badge" :class="[departure.delay < 0 ? 'badge-danger' : 'badge-warning']"
|
<span class="badge" :class="[departure.delay < 0 ? 'badge-danger' : 'badge-warning']"
|
||||||
v-if="departure.delay < 0 || departure.delay > 30">
|
v-if="departure.delay < 0 || departure.delay > 30">
|
||||||
{{ departure.delay|signed }}s
|
{{ departure.delay|signed }}s
|
||||||
</span>
|
</span>
|
||||||
<span class="departure__estimated">{{ departure.estimated.format('HH:mm') }}</span>
|
<span class="departure__estimated" v-if="departure.estimated && departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm')">{{ departure.estimated.format('HH:mm') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="departure__stop">
|
<div class="departure__stop">
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
width: 9rem;
|
width: 9rem;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
||||||
.departure__scheduled {
|
.departure__scheduled--delayed {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { Moment } from "moment";
|
|||||||
export interface Departure {
|
export interface Departure {
|
||||||
display: string;
|
display: string;
|
||||||
estimated: Moment;
|
estimated: Moment;
|
||||||
scheduled: Moment;
|
scheduled?: Moment;
|
||||||
stop: Stop;
|
stop: Stop;
|
||||||
line: Line;
|
line: Line;
|
||||||
delay: number;
|
delay: number;
|
||||||
|
@ -45,7 +45,7 @@ export const departures: Module<DeparturesState, RootState> = {
|
|||||||
const departures = await response.json() as Jsonified<Departure>[];
|
const departures = await response.json() as Jsonified<Departure>[];
|
||||||
commit('update', departures.map(departure => {
|
commit('update', departures.map(departure => {
|
||||||
departure.scheduled = moment.parseZone(departure.scheduled);
|
departure.scheduled = moment.parseZone(departure.scheduled);
|
||||||
departure.estimated = moment.parseZone(departure.estimated);
|
departure.estimated = departure.estimated && moment.parseZone(departure.estimated);
|
||||||
|
|
||||||
return departure as Departure;
|
return departure as Departure;
|
||||||
}));
|
}));
|
||||||
|
@ -61,7 +61,8 @@ class DeparturesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
||||||
{
|
{
|
||||||
$stops = $stops->getManyById($request->query->get('stop'))
|
$stops = $stops
|
||||||
|
->getManyById($request->query->get('stop'))
|
||||||
->flatMap([ $departures, 'getForStop' ])
|
->flatMap([ $departures, 'getForStop' ])
|
||||||
->sortBy(function (Departure $departure) {
|
->sortBy(function (Departure $departure) {
|
||||||
return $departure->getEstimated();
|
return $departure->getEstimated();
|
||||||
|
@ -38,15 +38,14 @@ class TrackEntity implements Entity, Fillable
|
|||||||
*
|
*
|
||||||
* @var LineEntity
|
* @var LineEntity
|
||||||
*
|
*
|
||||||
* @ORM\ManyToOne(targetEntity=LineEntity::class, fetch="EAGER")
|
* @ORM\ManyToOne(targetEntity=LineEntity::class, fetch="EAGER", inversedBy="tracks")
|
||||||
*/
|
*/
|
||||||
private $line;
|
private $line;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops in track
|
* Stops in track
|
||||||
* @var Collection
|
* @var Collection
|
||||||
* @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="EXTRA_LAZY", mappedBy="track", cascade={"persist"})
|
* @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
|
||||||
* @ORM\OrderBy({"order": "ASC"})
|
|
||||||
*/
|
*/
|
||||||
private $stopsInTrack;
|
private $stopsInTrack;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use App\Model\Trip;
|
|||||||
use App\Service\IdUtils;
|
use App\Service\IdUtils;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JMS\Serializer\Tests\Fixtures\Discriminator\Car;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
@ -26,7 +27,7 @@ class TripStopEntity implements Fillable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TripEntity
|
* @var TripEntity
|
||||||
* @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER")
|
* @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER", inversedBy="stops")
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
*/
|
*/
|
||||||
private $trip;
|
private $trip;
|
||||||
@ -98,7 +99,7 @@ class TripStopEntity implements Fillable
|
|||||||
|
|
||||||
public function getDeparture(): Carbon
|
public function getDeparture(): Carbon
|
||||||
{
|
{
|
||||||
return $this->departure;
|
return Carbon::instance($this->departure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDeparture(Carbon $departure): void
|
public function setDeparture(Carbon $departure): void
|
||||||
|
@ -3,31 +3,66 @@
|
|||||||
namespace App\Provider\Database;
|
namespace App\Provider\Database;
|
||||||
|
|
||||||
use App\Entity\StopEntity;
|
use App\Entity\StopEntity;
|
||||||
|
use App\Entity\StopInTrack;
|
||||||
|
use App\Entity\TrackEntity;
|
||||||
use App\Entity\TripStopEntity;
|
use App\Entity\TripStopEntity;
|
||||||
|
use App\Model\Departure;
|
||||||
|
use App\Model\Line;
|
||||||
use App\Model\Stop;
|
use App\Model\Stop;
|
||||||
|
use App\Model\Vehicle;
|
||||||
|
use App\Provider\ScheduleRepository;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Tightenco\Collect\Support\Collection;
|
||||||
use function Kadet\Functional\ref;
|
use function Kadet\Functional\ref;
|
||||||
|
|
||||||
class GenericScheduleRepository extends DatabaseRepository
|
class GenericScheduleRepository extends DatabaseRepository implements ScheduleRepository
|
||||||
{
|
|
||||||
const DEFAULT_DEPARTURES_COUNT = 8;
|
|
||||||
|
|
||||||
public function getDeparturesForStop(Stop $stop, \DateTime $from, int $count = 8)
|
|
||||||
{
|
{
|
||||||
|
public function getDeparturesForStop(
|
||||||
|
Stop $stop,
|
||||||
|
\DateTime $from,
|
||||||
|
int $count = ScheduleRepository::DEFAULT_DEPARTURES_COUNT
|
||||||
|
): Collection {
|
||||||
$query = $this->em
|
$query = $this->em
|
||||||
->createQueryBuilder()
|
->createQueryBuilder()
|
||||||
->select('s')
|
->select('ts', 't')
|
||||||
->from(TripStopEntity::class, 's')
|
->from(TripStopEntity::class, 'ts')
|
||||||
->where('s.arrival >= :from')
|
->where('ts.departure >= :from')
|
||||||
->andWhere('s.stop = :stop')
|
->andWhere('ts.stop = :stop')
|
||||||
|
->join('ts.trip', 't')
|
||||||
|
->orderBy('ts.departure', 'ASC')
|
||||||
->setMaxResults($count)
|
->setMaxResults($count)
|
||||||
->getQuery()
|
->getQuery();
|
||||||
;
|
|
||||||
|
|
||||||
$schedule = collect($query->execute([
|
$schedule = collect($query->execute([
|
||||||
'from' => $from,
|
'from' => $from,
|
||||||
'stop' => $this->reference(StopEntity::class, $stop),
|
'stop' => $this->reference(StopEntity::class, $stop),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
return $schedule->map(ref([$this, 'convert']));
|
$this->em->createQueryBuilder()
|
||||||
|
->select('t', 's', 'st')
|
||||||
|
->from(TrackEntity::class, 't')
|
||||||
|
->join('t.stopsInTrack', 's')
|
||||||
|
->join('s.stop', 'st')
|
||||||
|
->where('t.id in (:tracks)')
|
||||||
|
->orderBy('s.order', 'DESC')
|
||||||
|
->getQuery()
|
||||||
|
->execute([
|
||||||
|
':tracks' => $schedule->map(function (TripStopEntity $stop) {
|
||||||
|
return $stop->getTrip()->getTrack()->getId();
|
||||||
|
})->all()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $schedule->map(function (TripStopEntity $entity) use ($stop) {
|
||||||
|
$line = $entity->getTrip()->getTrack()->getLine();
|
||||||
|
/** @var StopEntity $last */
|
||||||
|
$last = $entity->getTrip()->getTrack()->getStopsInTrack()->last()->getStop();
|
||||||
|
|
||||||
|
return Departure::createFromArray([
|
||||||
|
'scheduled' => $entity->getDeparture(),
|
||||||
|
'stop' => $stop,
|
||||||
|
'display' => $last->getName(),
|
||||||
|
'line' => $this->convert($line),
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
17
src/Provider/ScheduleRepository.php
Normal file
17
src/Provider/ScheduleRepository.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Provider;
|
||||||
|
|
||||||
|
use App\Model\Stop;
|
||||||
|
use Tightenco\Collect\Support\Collection;
|
||||||
|
|
||||||
|
interface ScheduleRepository
|
||||||
|
{
|
||||||
|
const DEFAULT_DEPARTURES_COUNT = 8;
|
||||||
|
|
||||||
|
public function getDeparturesForStop(
|
||||||
|
Stop $stop,
|
||||||
|
\DateTime $from,
|
||||||
|
int $count = ScheduleRepository::DEFAULT_DEPARTURES_COUNT
|
||||||
|
): Collection;
|
||||||
|
}
|
@ -16,6 +16,7 @@ use App\Model\Location;
|
|||||||
use App\Service\DataUpdater;
|
use App\Service\DataUpdater;
|
||||||
use App\Service\IdUtils;
|
use App\Service\IdUtils;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Cerbero\JsonObjects\JsonObjects;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
@ -24,6 +25,7 @@ use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
|||||||
use Symfony\Component\Console\Output\NullOutput;
|
use Symfony\Component\Console\Output\NullOutput;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Tightenco\Collect\Support\Collection;
|
use Tightenco\Collect\Support\Collection;
|
||||||
|
use function Cerbero\JsonObjects\JsonObjects;
|
||||||
use function Kadet\Functional\ref;
|
use function Kadet\Functional\ref;
|
||||||
|
|
||||||
class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||||
@ -63,6 +65,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
|
|
||||||
public function update(DataUpdateEvent $event)
|
public function update(DataUpdateEvent $event)
|
||||||
{
|
{
|
||||||
|
$output = $event->getOutput();
|
||||||
|
|
||||||
$provider = ProviderEntity::createFromArray([
|
$provider = ProviderEntity::createFromArray([
|
||||||
'name' => $this->provider->getName(),
|
'name' => $this->provider->getName(),
|
||||||
'class' => ZtmGdanskProvider::class,
|
'class' => ZtmGdanskProvider::class,
|
||||||
@ -76,8 +80,13 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
$this->getOperators($provider, $event)->each($save);
|
$this->getOperators($provider, $event)->each($save);
|
||||||
$this->getStops($provider, $event)->each($save);
|
$this->getStops($provider, $event)->each($save);
|
||||||
$this->getTracks($provider, $event)->each($save);
|
$this->getTracks($provider, $event)->each($save);
|
||||||
|
|
||||||
$lines = $this->getLines($provider, $event)->each($save);
|
$lines = $this->getLines($provider, $event)->each($save);
|
||||||
|
|
||||||
|
$output->write('Flushing all things into database...');
|
||||||
|
$this->em->flush();
|
||||||
|
$this->em->clear();
|
||||||
|
$output->writeln('done');
|
||||||
|
|
||||||
$this->updateSchedule($provider, $lines, $event);
|
$this->updateSchedule($provider, $lines, $event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,12 +153,16 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
$output->writeln(sprintf('done (%d)', count($stops)));
|
$output->writeln(sprintf('done (%d)', count($stops)));
|
||||||
|
|
||||||
$this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops)));
|
$this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops)));
|
||||||
return collect($stops)->map(function ($stop) use ($provider) {
|
return collect($stops)
|
||||||
|
->filter(function ($stop) {
|
||||||
|
return $stop['nonpassenger'] !== null && $stop['nonpassenger'] !== 1;
|
||||||
|
})
|
||||||
|
->map(function ($stop) use ($provider) {
|
||||||
return StopEntity::createFromArray([
|
return StopEntity::createFromArray([
|
||||||
'id' => $this->ids->generate($provider, $stop['stopId']),
|
'id' => $this->ids->generate($provider, $stop['stopId']),
|
||||||
'name' => trim($stop['stopName'] ?? $stop['stopDesc']),
|
'name' => trim($stop['stopName'] ?? $stop['stopDesc']),
|
||||||
'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] : null),
|
'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] : null),
|
||||||
'latitude' => Location::fromArray($stop['stopLat']),
|
'latitude' => $stop['stopLat'],
|
||||||
'longitude' => $stop['stopLon'],
|
'longitude' => $stop['stopLon'],
|
||||||
'onDemand' => (bool)$stop['onDemand'],
|
'onDemand' => (bool)$stop['onDemand'],
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
@ -157,7 +170,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTracks(ProviderEntity $provider, DataUpdateEvent $event)
|
public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, $stops = [])
|
||||||
{
|
{
|
||||||
ini_set('memory_limit', '2G');
|
ini_set('memory_limit', '2G');
|
||||||
|
|
||||||
@ -215,32 +228,29 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
'routeId' => $this->ids->of($line),
|
'routeId' => $this->ids->of($line),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
$schedule = file_get_contents($url);
|
$schedule = JsonObjects::from($url, 'stopTimes.*');
|
||||||
$schedule = json_decode($schedule, true)['stopTimes'];
|
$trips = new Collection();
|
||||||
$schedule = collect($schedule)->groupBy(function ($stop) {
|
|
||||||
return sprintf("%s-%d", $stop['busServiceName'], $stop['order']);
|
|
||||||
});
|
|
||||||
|
|
||||||
collect($schedule)->map(function (Collection $trips, $id) use ($provider) {
|
$schedule->each(function ($stop) use ($provider, &$trips) {
|
||||||
$entity = TripEntity::createFromArray([
|
$id = sprintf('%s-%d', $stop['busServiceName'], $stop['order']);
|
||||||
|
$trip = $trips[$id] ?? $trips[$id] = (function () use ($stop, $id, $provider) {
|
||||||
|
$trip = TripEntity::createFromArray([
|
||||||
'id' => $this->ids->generate($provider, $id),
|
'id' => $this->ids->generate($provider, $id),
|
||||||
'operator' => $this->em->getReference(
|
'operator' => $this->em->getReference(
|
||||||
OperatorEntity::class,
|
OperatorEntity::class,
|
||||||
$this->ids->generate($provider, $trips->first()['agencyId'])
|
$this->ids->generate($provider, $stop['agencyId'])
|
||||||
),
|
),
|
||||||
'track' => $this->em->getReference(
|
'track' => $this->em->getReference(
|
||||||
TrackEntity::class,
|
TrackEntity::class,
|
||||||
$this->ids->generate($provider, $trips->first()['tripId'])
|
$this->ids->generate($provider, sprintf('R%sT%s', $stop['routeId'], $stop['tripId']))
|
||||||
),
|
),
|
||||||
'variant' => $trips->first(function ($trip) {
|
|
||||||
return !empty($trip['noteSymbol']);
|
|
||||||
}, ['noteSymbol' => null])['noteSymbol'],
|
|
||||||
'note' => $trips->first(function ($trip) {
|
|
||||||
return !empty($trip['noteSymbol']);
|
|
||||||
}, ['noteDescription' => null])['noteDescription'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$stops = $trips->map(function ($stop) use ($entity, $provider) {
|
$this->em->persist($trip);
|
||||||
|
|
||||||
|
return $trip;
|
||||||
|
})();
|
||||||
|
|
||||||
$base = Carbon::create(1899, 12, 30, 00, 00, 00);
|
$base = Carbon::create(1899, 12, 30, 00, 00, 00);
|
||||||
$date = Carbon::createFromFormat('Y-m-d', $stop['date'])->setTime(00, 00, 00);
|
$date = Carbon::createFromFormat('Y-m-d', $stop['date'])->setTime(00, 00, 00);
|
||||||
|
|
||||||
@ -250,8 +260,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
$arrival = (clone $date)->add($arrival);
|
$arrival = (clone $date)->add($arrival);
|
||||||
$departure = (clone $date)->add($departure);
|
$departure = (clone $date)->add($departure);
|
||||||
|
|
||||||
return TripStopEntity::createFromArray([
|
$entity = TripStopEntity::createFromArray([
|
||||||
'trip' => $entity,
|
'trip' => $trip,
|
||||||
'stop' => $this->em->getReference(
|
'stop' => $this->em->getReference(
|
||||||
StopEntity::class,
|
StopEntity::class,
|
||||||
$this->ids->generate($provider, $stop['stopId'])
|
$this->ids->generate($provider, $stop['stopId'])
|
||||||
@ -260,17 +270,17 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
'arrival' => $arrival,
|
'arrival' => $arrival,
|
||||||
'departure' => $departure,
|
'departure' => $departure,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$entity->setTrip($trip);
|
||||||
|
$this->em->persist($entity);
|
||||||
});
|
});
|
||||||
|
|
||||||
$entity->setStops($stops);
|
|
||||||
|
|
||||||
return $entity;
|
|
||||||
})->each(ref([$this->em, 'persist']));
|
|
||||||
|
|
||||||
$this->logger->debug(sprintf('Got schedule for line %s from ZTM Gdańsk', $line->getId()));
|
$this->logger->debug(sprintf('Got schedule for line %s from ZTM Gdańsk', $line->getId()));
|
||||||
|
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
$this->em->clear();
|
$this->em->clear();
|
||||||
|
|
||||||
|
gc_collect_cycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSubscribedEvents()
|
public static function getSubscribedEvents()
|
||||||
@ -296,7 +306,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$progress->finish();
|
$progress->finish();
|
||||||
$progress->
|
$event->getOutput()->writeln("");
|
||||||
$event->getOutput()->writeln("done");
|
$event->getOutput()->writeln("done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ use App\Model\Vehicle;
|
|||||||
use App\Provider\Database\GenericScheduleRepository;
|
use App\Provider\Database\GenericScheduleRepository;
|
||||||
use App\Provider\DepartureRepository;
|
use App\Provider\DepartureRepository;
|
||||||
use App\Provider\LineRepository;
|
use App\Provider\LineRepository;
|
||||||
|
use App\Provider\ScheduleRepository;
|
||||||
use App\Service\Proxy\ReferenceFactory;
|
use App\Service\Proxy\ReferenceFactory;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Tightenco\Collect\Support\Collection;
|
use Tightenco\Collect\Support\Collection;
|
||||||
@ -24,13 +25,17 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
|
|||||||
/** @var ReferenceFactory */
|
/** @var ReferenceFactory */
|
||||||
private $reference;
|
private $reference;
|
||||||
|
|
||||||
|
/** @var ScheduleRepository */
|
||||||
|
private $schedule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param LineRepository $lines
|
* @param LineRepository $lines
|
||||||
*/
|
*/
|
||||||
public function __construct(LineRepository $lines, ReferenceFactory $reference)
|
public function __construct(LineRepository $lines, ScheduleRepository $schedule, ReferenceFactory $reference)
|
||||||
{
|
{
|
||||||
$this->lines = $lines;
|
$this->lines = $lines;
|
||||||
$this->reference = $reference;
|
$this->reference = $reference;
|
||||||
|
$this->schedule = $schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getForStop(Stop $stop): Collection
|
public function getForStop(Stop $stop): Collection
|
||||||
|
@ -12,6 +12,7 @@ use App\Provider\DepartureRepository;
|
|||||||
use App\Provider\LineRepository;
|
use App\Provider\LineRepository;
|
||||||
use App\Provider\MessageRepository;
|
use App\Provider\MessageRepository;
|
||||||
use App\Provider\Provider;
|
use App\Provider\Provider;
|
||||||
|
use App\Provider\ScheduleRepository;
|
||||||
use App\Provider\StopRepository;
|
use App\Provider\StopRepository;
|
||||||
use App\Provider\TrackRepository;
|
use App\Provider\TrackRepository;
|
||||||
use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository};
|
use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository};
|
||||||
@ -67,7 +68,7 @@ class ZtmGdanskProvider implements Provider
|
|||||||
$schedule = $schedule->withProvider($provider);
|
$schedule = $schedule->withProvider($provider);
|
||||||
|
|
||||||
$this->lines = $lines;
|
$this->lines = $lines;
|
||||||
$this->departures = new ZtmGdanskDepartureRepository($lines, $referenceFactory);
|
$this->departures = new ZtmGdanskDepartureRepository($lines, $schedule, $referenceFactory);
|
||||||
$this->stops = $stops;
|
$this->stops = $stops;
|
||||||
$this->messages = $messages;
|
$this->messages = $messages;
|
||||||
$this->tracks = $tracks;
|
$this->tracks = $tracks;
|
||||||
|
@ -35,7 +35,7 @@ class DataUpdater
|
|||||||
$connection->getConfiguration()->setSQLLogger(null);
|
$connection->getConfiguration()->setSQLLogger(null);
|
||||||
$schema = $connection->getSchemaManager();
|
$schema = $connection->getSchemaManager();
|
||||||
|
|
||||||
$path = $connection->getParams()['path'];
|
$path = preg_replace("~sqlite:///~si", '', $connection->getParams()['path']);
|
||||||
$backup = "$path.backup";
|
$backup = "$path.backup";
|
||||||
|
|
||||||
copy($path, $backup);
|
copy($path, $backup);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"cerbero/json-objects": {
|
||||||
|
"version": "v1.1.2"
|
||||||
|
},
|
||||||
"doctrine/annotations": {
|
"doctrine/annotations": {
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
@ -175,12 +178,18 @@
|
|||||||
"psr/container": {
|
"psr/container": {
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
|
"psr/http-message": {
|
||||||
|
"version": "1.0.1"
|
||||||
|
},
|
||||||
"psr/log": {
|
"psr/log": {
|
||||||
"version": "1.0.2"
|
"version": "1.0.2"
|
||||||
},
|
},
|
||||||
"psr/simple-cache": {
|
"psr/simple-cache": {
|
||||||
"version": "1.0.1"
|
"version": "1.0.1"
|
||||||
},
|
},
|
||||||
|
"salsify/json-streaming-parser": {
|
||||||
|
"version": "v8.1.0"
|
||||||
|
},
|
||||||
"sensio/framework-extra-bundle": {
|
"sensio/framework-extra-bundle": {
|
||||||
"version": "5.2",
|
"version": "5.2",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
Loading…
Reference in New Issue
Block a user