From 56a53740cefbd1f7aa744ccf5f2196657bbe1b43 Mon Sep 17 00:00:00 2001 From: Clemens Vasters Date: Wed, 18 Sep 2024 16:37:33 +0200 Subject: [PATCH] docs and producer fixes Signed-off-by: Clemens Vasters --- DATABASE.md | 273 +++ gtfs/CONTAINER.md | 6 + .../src/gtfs_rt_bridge/gtfs_cli.py | 6 +- .../src/gtfs_rt_producer_data/__init__.py | 6 +- .../generaltransitfeedrealtime/__init__.py | 4 +- .../generaltransitfeedrealtime/alert/alert.py | 8 +- .../alert/entityselector.py | 4 +- .../alert/timerange.py | 4 +- .../alert/translatedstring.py | 4 +- .../translatedstring_types/translation.py | 4 +- .../alert/tripdescriptor.py | 4 +- .../trip/tripdescriptor.py | 4 +- .../trip/tripupdate.py | 8 +- .../trip/tripupdate_types/stoptimeevent.py | 4 +- .../trip/tripupdate_types/stoptimeupdate.py | 6 +- .../trip/vehicledescriptor.py | 4 +- .../vehicle/position.py | 4 +- .../vehicle/tripdescriptor.py | 4 +- .../vehicle/vehicledescriptor.py | 4 +- .../vehicle/vehicleposition.py | 6 +- .../generaltransitfeedstatic/__init__.py | 46 +- .../generaltransitfeedstatic/agency.py | 4 +- .../generaltransitfeedstatic/areas.py | 4 +- .../generaltransitfeedstatic/attributions.py | 4 +- .../generaltransitfeedstatic/bookingrules.py | 4 +- .../generaltransitfeedstatic/calendar.py | 4 +- .../generaltransitfeedstatic/calendardates.py | 4 +- .../fareattributes.py | 4 +- .../generaltransitfeedstatic/farelegrules.py | 4 +- .../generaltransitfeedstatic/faremedia.py | 4 +- .../generaltransitfeedstatic/fareproducts.py | 4 +- .../generaltransitfeedstatic/farerules.py | 4 +- .../faretransferrules.py | 4 +- .../generaltransitfeedstatic/feedinfo.py | 4 +- .../generaltransitfeedstatic/frequencies.py | 4 +- .../generaltransitfeedstatic/levels.py | 4 +- .../locationgeojson.py | 4 +- .../locationgroups.py | 4 +- .../locationgroupstores.py | 4 +- .../generaltransitfeedstatic/networks.py | 4 +- .../generaltransitfeedstatic/pathways.py | 4 +- .../generaltransitfeedstatic/routenetworks.py | 4 +- .../generaltransitfeedstatic/routes.py | 6 +- .../generaltransitfeedstatic/shapes.py | 4 +- .../generaltransitfeedstatic/stopareas.py | 4 +- .../generaltransitfeedstatic/stops.py | 6 +- .../generaltransitfeedstatic/stoptimes.py | 6 +- .../generaltransitfeedstatic/timeframes.py | 4 +- .../generaltransitfeedstatic/transfers.py | 4 +- .../generaltransitfeedstatic/translations.py | 4 +- .../generaltransitfeedstatic/trips.py | 8 +- ..._generaltransitfeedrealtime_alert_alert.py | 13 +- ...ransitfeedrealtime_alert_entityselector.py | 17 +- ...eraltransitfeedrealtime_alert_timerange.py | 9 +- ...nsitfeedrealtime_alert_translatedstring.py | 5 +- ...lert_translatedstring_types_translation.py | 9 +- ...ransitfeedrealtime_alert_tripdescriptor.py | 21 +- ...transitfeedrealtime_trip_tripdescriptor.py | 21 +- ...eraltransitfeedrealtime_trip_tripupdate.py | 13 +- ...ime_trip_tripupdate_types_stoptimeevent.py | 13 +- ...me_trip_tripupdate_types_stoptimeupdate.py | 11 +- ...nsitfeedrealtime_trip_vehicledescriptor.py | 13 +- ...raltransitfeedrealtime_vehicle_position.py | 21 +- ...nsitfeedrealtime_vehicle_tripdescriptor.py | 21 +- ...tfeedrealtime_vehicle_vehicledescriptor.py | 13 +- ...sitfeedrealtime_vehicle_vehicleposition.py | 15 +- ...er_data_generaltransitfeedstatic_agency.py | 33 +- ...cer_data_generaltransitfeedstatic_areas.py | 17 +- ...a_generaltransitfeedstatic_attributions.py | 45 +- ...a_generaltransitfeedstatic_bookingrules.py | 17 +- ..._data_generaltransitfeedstatic_calendar.py | 13 +- ..._generaltransitfeedstatic_calendardates.py | 9 +- ...generaltransitfeedstatic_fareattributes.py | 29 +- ...a_generaltransitfeedstatic_farelegrules.py | 25 +- ...data_generaltransitfeedstatic_faremedia.py | 17 +- ...a_generaltransitfeedstatic_fareproducts.py | 17 +- ...data_generaltransitfeedstatic_farerules.py | 21 +- ...eraltransitfeedstatic_faretransferrules.py | 29 +- ..._data_generaltransitfeedstatic_feedinfo.py | 37 +- ...ta_generaltransitfeedstatic_frequencies.py | 21 +- ...er_data_generaltransitfeedstatic_levels.py | 13 +- ...eneraltransitfeedstatic_locationgeojson.py | 13 +- ...generaltransitfeedstatic_locationgroups.py | 17 +- ...altransitfeedstatic_locationgroupstores.py | 13 +- ..._data_generaltransitfeedstatic_networks.py | 17 +- ..._data_generaltransitfeedstatic_pathways.py | 49 +- ..._generaltransitfeedstatic_routenetworks.py | 13 +- ...er_data_generaltransitfeedstatic_routes.py | 43 +- ...er_data_generaltransitfeedstatic_shapes.py | 21 +- ...data_generaltransitfeedstatic_stopareas.py | 13 +- ...cer_data_generaltransitfeedstatic_stops.py | 55 +- ...data_generaltransitfeedstatic_stoptimes.py | 31 +- ...ata_generaltransitfeedstatic_timeframes.py | 13 +- ...data_generaltransitfeedstatic_transfers.py | 17 +- ...a_generaltransitfeedstatic_translations.py | 17 +- ...cer_data_generaltransitfeedstatic_trips.py | 33 +- .../producer.py | 1537 +---------------- gtfs/{xreg => kql}/create-kql-script.ps1 | 4 +- gtfs/{xreg => kql}/gtfs.kql | 4 +- gtfs/xreg/gtfs.xreg.json | 264 +-- noaa/CONTAINER.md | 6 + noaa/{noaa => kql}/noaa.kql | 0 noaa/kql/noaa.kql.md | 2 + {gtfs/xreg => noaa/kql}/run-kql-script.ps1 | 0 noaa/noaa/run-kql-script.ps1 | 38 - noaa/{noaa => xreg}/noaa.avsc | 0 noaa/{noaa => xreg}/noaa.xreg.json | 0 pegelonline/CONTAINER.md | 6 + pegelonline/kql/create-kql-script.ps1 | 13 + pegelonline/{xreg => kql}/pegelonline.kql | 4 + .../pegelonline_producer_data/pyproject.toml | 2 +- .../de/wsv/pegelonline/currentmeasurement.py | 4 +- .../de/wsv/pegelonline/station.py | 4 +- .../de/wsv/pegelonline/water.py | 4 +- ...a_de_wsv_pegelonline_currentmeasurement.py | 21 +- ...roducer_data_de_wsv_pegelonline_station.py | 33 +- ..._producer_data_de_wsv_pegelonline_water.py | 9 +- .../pyproject.toml | 2 +- .../producer.py | 54 +- pegelonline/xreg/create-kql-script.ps1 | 11 - pegelonline/xreg/pegelonline.xreg.json | 26 +- pegelonline/xreg/schemas.avsc | 107 -- rss/CONTAINER.md | 6 + rss/{xreg => kql}/create-kql-script.ps1 | 7 +- rss/{xreg => kql}/feeds.kql | 0 .../producer.py | 2 +- rss/xreg/run-kql-script.ps1 | 38 - tools/clean-user-path.ps1 | 32 + tools/install-avrotize.ps1 | 74 + tools/install-kusto-cli.ps1 | 86 + tools/media/eventhouse-details.png | Bin 0 -> 18752 bytes tools/media/get-data.png | Bin 0 -> 57298 bytes tools/media/inspect-data.png | Bin 0 -> 43210 bytes tools/media/pick-destination.png | Bin 0 -> 99167 bytes tools/run-kql-script.ps1 | 19 + 135 files changed, 1446 insertions(+), 2439 deletions(-) create mode 100644 DATABASE.md rename gtfs/{xreg => kql}/create-kql-script.ps1 (95%) rename gtfs/{xreg => kql}/gtfs.kql (97%) rename noaa/{noaa => kql}/noaa.kql (100%) create mode 100644 noaa/kql/noaa.kql.md rename {gtfs/xreg => noaa/kql}/run-kql-script.ps1 (100%) delete mode 100644 noaa/noaa/run-kql-script.ps1 rename noaa/{noaa => xreg}/noaa.avsc (100%) rename noaa/{noaa => xreg}/noaa.xreg.json (100%) create mode 100644 pegelonline/kql/create-kql-script.ps1 rename pegelonline/{xreg => kql}/pegelonline.kql (98%) delete mode 100644 pegelonline/xreg/create-kql-script.ps1 delete mode 100644 pegelonline/xreg/schemas.avsc rename rss/{xreg => kql}/create-kql-script.ps1 (81%) rename rss/{xreg => kql}/feeds.kql (100%) delete mode 100644 rss/xreg/run-kql-script.ps1 create mode 100644 tools/clean-user-path.ps1 create mode 100644 tools/install-avrotize.ps1 create mode 100644 tools/install-kusto-cli.ps1 create mode 100644 tools/media/eventhouse-details.png create mode 100644 tools/media/get-data.png create mode 100644 tools/media/inspect-data.png create mode 100644 tools/media/pick-destination.png create mode 100644 tools/run-kql-script.ps1 diff --git a/DATABASE.md b/DATABASE.md new file mode 100644 index 0000000..54bcf9b --- /dev/null +++ b/DATABASE.md @@ -0,0 +1,273 @@ +# API Bridges - Setting up a KQL database + +The APi bridges write data to a Kafka topic or Azure Event Hubs +or Fabric Event Streams. From Event Hubs and Event Streams, you can easily feed +this data into a Fabric Eventhouse or Azure Data Explorer (Kusto) database to +analyze and visualize it. + +This document explains how to set up a Kusto database and ingest data from the +API bridges. The principles are the same for all the bridges. + +## Creating the database - Microsoft Fabric Eventhouse + +First, you need access to Microsoft Fabric. If you don't have access yet, you +can easily set up a trial account for yourself. To set up a trial account, +follow the instructions in the +[Microsoft Fabric documentation](https://learn.microsoft.com/en-us/fabric/get-started/fabric-trial). + +If that's "TL;DR" for you, [click here and get going](https://app.fabric.microsoft.com/home). + +To set up a KQL database in Microsoft Fabric, follow the following steps: + +1. [Create an Eventhouse](https://learn.microsoft.com/en-us/fabric/real-time-intelligence/create-eventhouse) or reuse an existing one. +2. [Create a KQL database](https://learn.microsoft.com/en-us/fabric/real-time-intelligence/create-database) in the Eventhouse. + +Once you have set up the KQL database, collect these two pieces of information: + +1. The `databaseName` of the KQL database. +2. The `clusterUri` of the Eventhouse. You can find this in the Eventhouse + overview in the Microsoft Fabric portal under "Eventhouse details". + + ![Cluster URI](tools/media/eventhouse-details.png) + +## Creating the database - Azure Data Explorer (Kusto) + +First, you need an Azure subscription. If you don't have an Azure subscription +yet, you can easily set up a trial account for yourself. To set up a trial +account, follow the instructions in the +[Azure documentation](https://azure.microsoft.com/en-us/free/). + +To set up a KQL database in Azure Data Explorer (Kusto), follow the steps in the [Create a Kusto cluster and database](https://docs.microsoft.com/en-us/azure/data-explorer/create-cluster-database-portal) article. + +Once you have set up the KQL database, collect these two pieces of information: + +1. The `databaseName` of the KQL database. +2. The `clusterUri` of the Kusto cluster. You can find this in the Azure portal + under "Overview" in the Azure Data Explorer (Kusto) resource. It's the value + of the "URI" field. + +## Adding the event data schemas to the KQL database + +The KQL scripts in the projects contains the necessary table schemas, +materialized views, and update policies to organize the event +data in the the KQL database. Consider this your "bronze" layer. + +The scripts are located here: +- GTFS: [gtfs.kql](gtfs/kql/gtfs.kql) +- NOAA: [noaa.kql](noaa/kql/noaa.kql) +- PegelOnline: [pegelonline.kql](pegelonline/kql/pegelonline.kql) +- RSS: [rss.kql](rss/kql/feeds.kql) + +You can run the script one-by-one in the Kusto Query Language (KQL) editor in +the Fabric or Azure database portal, or you can use the `kusto.cli` tool for +which you find two helper scripts in the [tools](tools) directory. + +### Installing the Kusto CLI tool + +To install the Kusto CLI tool, run the following command: + +```shell +.\tools\install-kusto-cli.ps1 +``` + +The script downloads the Kusto CLI tool, installs it into the `KustoCLI` directory of your user profile, and adds tools directory inside of that to the user's PATH. If you run the tool from Windows Powershell, the .NET 4.7 version is installed, if you run from Powershell 7+, the .NET 6.0 version is installed. + +### Running the KQL script + +To run the KQL script, use the following command: + +```shell +.\tools\run-kql-script.ps1 -clusterUri '' -databaseName '' -script .\gtfs\kql\gtfs.kql +``` + +Replace `` and `` with the values you collected earlier. + +This assumes that you run the script from the root of the repository. If you run it from a different location, adjust the path to the script accordingly. + +### The schema and how it works + +The script creates a table for each payload schema of every event that is being +sent by the bridge. The table contains the "top level" fields of the payload +schema flattened into columns. If a payload field is an object or an array, the +column type is `dynamic`. The CloudEvents metadata is stored in the table as +well, with each attribute name prefixed with `___`. + +Example: + +```kusto +.create-merge table [Trips] ( + [routeId]: string, + [serviceDates]: dynamic, + [serviceExceptions]: dynamic, + [tripId]: string, + [tripHeadsign]: string, + [tripShortName]: string, + [directionId]: string, + [blockId]: string, + [shapeId]: string, + [wheelchairAccessible]: string, + [bikesAllowed]: string, + [___type]: string, + [___source]: string, + [___id]: string, + [___time]: datetime, + [___subject]: string +); +``` + +The script also creates a materialized view for each payload schema that gives +you the latest event for each unique combination of the CloudEvent `___type`, +`___source`, and `___subject`. This is useful for querying the latest state of +each entity. The bridge will generally populate the `___subject` with a key +value for the entity (the `tripId` in the example above), so you can easily +query the latest state and avoid reading duplicates in the form of older +versions. + +```kusto +.create materialized-view with (backfill=true) TripsLatest on table Trips { + Trips | summarize arg_max(___time, *) by ___type, ___source, ___subject +} +``` + +You will also find that the input schema's descriptive metadata is added +to the table as table and column docstrings. + +Inside the docstrings you may find two fields: + +- `description`: A human-readable description of the field. +- `schema`: An Apache Avro schema that describes the field's data type and possible values. This is added if the available type information is richer than what can be expressed in KQL. + +Example: + +``` kusto +.alter table [Trips] column-docstrings ( + [routeId]: "{\"description\": \"Identifies a route.\"}", + [tripId]: "{\"description\": \"Identifies a trip.\"}", + [tripHeadsign]: "{\"description\": \"Text that appears on signage identifying the trip's destination to riders.\", \"schema\": [\"null\", \"string\"]}", + [tripShortName]: "{\"description\": \"Public facing text used to identify the trip to riders.\", \"schema\": [\"null\", \"string\"]}", + [directionId]: "{\"description\": \"Indicates the direction of travel for a trip.\", \"schema\": {\"type\": \"enum\", \"name\": \"DirectionId\", \"namespace\": \"GeneralTransitFeedStatic\", \"symbols\": [\"OUTBOUND\", \"INBOUND\"], \"doc\": \"Indicates the direction of travel for a trip. Symbols: OUTBOUND - Travel in one direction; INBOUND - Travel in the opposite direction.\"}}", + [blockId]: "{\"description\": \"Identifies the block to which the trip belongs.\", \"schema\": [\"null\", \"string\"]}", + [shapeId]: "{\"description\": \"Identifies a geospatial shape describing the vehicle travel path for a trip.\", \"schema\": [\"null\", \"string\"]}", + [wheelchairAccessible]: "{\"description\": \"Indicates wheelchair accessibility.\", \"schema\": {\"type\": \"enum\", \"name\": \"WheelchairAccessible\", \"namespace\": \"GeneralTransitFeedStatic\", \"symbols\": [\"NO_INFO\", \"WHEELCHAIR_ACCESSIBLE\", \"NOT_WHEELCHAIR_ACCESSIBLE\"], \"doc\": \"Indicates wheelchair accessibility. Symbols: NO_INFO - No accessibility information for the trip; WHEELCHAIR_ACCESSIBLE - Vehicle can accommodate at least one rider in a wheelchair; NOT_WHEELCHAIR_ACCESSIBLE - No riders in wheelchairs can be accommodated on this trip.\"}}", + [bikesAllowed]: "{\"description\": \"Indicates whether bikes are allowed.\", \"schema\": {\"type\": \"enum\", \"name\": \"BikesAllowed\", \"namespace\": \"GeneralTransitFeedStatic\", \"symbols\": [\"NO_INFO\", \"BICYCLE_ALLOWED\", \"BICYCLE_NOT_ALLOWED\"], \"doc\": \"Indicates whether bikes are allowed. Symbols: NO_INFO - No bike information for the trip; BICYCLE_ALLOWED - Vehicle can accommodate at least one bicycle; BICYCLE_NOT_ALLOWED - No bicycles are allowed on this trip.\"}}", + [___type] : 'Event type', + [___source]: 'Context origin/source of the event', + [___id]: 'Event identifier', + [___time]: 'Event generation time', + [___subject]: 'Context subject of the event' +); +``` + +The script also creates an update policy for each table that imports "its" events from +the `_cloudevents_ingest` table. This is explained further in the next section. + +````kusto +.alter table [Trips] policy update +``` +[{ + "IsEnabled": true, + "Source": "_cloudevents_dispatch", + "Query": "_cloudevents_dispatch | where (specversion == '1.0' and type == 'GeneralTransitFeedStatic.Trips') | project['routeId'] = tostring(data.['routeId']),['serviceDates'] = todynamic(data.['serviceDates']),['serviceExceptions'] = todynamic(data.['serviceExceptions']),['tripId'] = tostring(data.['tripId']),['tripHeadsign'] = tostring(data.['tripHeadsign']),['tripShortName'] = tostring(data.['tripShortName']),['directionId'] = tostring(data.['directionId']),['blockId'] = tostring(data.['blockId']),['shapeId'] = tostring(data.['shapeId']),['wheelchairAccessible'] = tostring(data.['wheelchairAccessible']),['bikesAllowed'] = tostring(data.['bikesAllowed']),___type = type,___source = source,___id = ['id'],___time = ['time'],___subject = subject", + "IsTransactional": false, + "PropagateIngestionProperties": true, +}] +``` +```` + +Finally, there are two ingestion mappings created for each table. The `_json_flat` mapping assumes that the +arriving events are already in the flattened form of the table schema. The `_json_ce_structured` mapping assumes that the arriving events are in CloudEvents structured JSON format and extracts the payload columns from the `data` field. + + +## Ingesting data from the API bridge + +Now that you have set up the KQL database and added the necessary schemas, you +still need to wire up the API bridge to the KQL database. + +The table schema elements added by the script allow for several avenues for +ingesting data. We will discuss two of them here: + +### Ingesting events data via the `_cloudevents_dispatch` table. + +In this scenario, you will set up your KQL database to ingest data from the +Event Stream or Event Hub into the `_cloudevents_dispatch` table, using the +`_cloudevents_dispatch_json` JSON ingestion mapping. + +#### Setting up the ingestion in Microsoft Fabric + +Before you start, the bridge should be running or should at least already have +run once to send some events to the target Event Stream or Event Hub. It is +required for data to be in the Event Stream or Event Hub to finish the setup. + +1. In the Microsoft Fabric portal, navigate to the Eventhouse and database you + set up. + +2. Find the "Get Data" button in the ribbon, and click it or expand its menu. + Select either "Event Hub" or "Event Stream" depending on which you are + publishing to:
+ +3. In the "Pick a destination table and configure the source" dialog, select the + `_cloudevents_dispatch` table, then complete the source configuration.
+ + Detailed instructions for how to connect to Event Hubs and Event Streams sources can + be found in the documentation: + + - [Get data from Azure Event Hubs](https://learn.microsoft.com/en-us/fabric/real-time-intelligence/get-data-event-hub) + + - [Get data from Azure Event Streams](https://learn.microsoft.com/en-us/fabric/real-time-intelligence/get-data-event-streams) + +4. It is recommended to open up the "Advanced filters" section and set the + "Event retrieval start date" to date well before you started the bridge for + the first time. + +5. Click "Next". On the upper right hand side of the "Inspect the data" dialog, + make sure that "Format" is "JSON" and then click "Advanced", select "existing + mapping" in the box and choose the `_cloudevents_dispatch_mapping` mapping. +
+ +6. Click "Finish" to start the ingestion. + +Once you've completed these steps, events will start showing up in the `_cloudevents_dispatch` table +and the update policies will take care of importing the events into the per-event-type tables. + +#### Setting up the ingestion in Azure Data Explorer (Kusto) + +With Azure Data Explorer, the steps are similar to the ones for Microsoft Fabric, but the +portal entry point is different. + +Follow the instructions in the +[Create an Event Hubs data connection for Azure Data Explorer](https://learn.microsoft.com/en-us/azure/data-explorer/create-event-hubs-connection?tabs=get-data%2Cget-data-2) +article, and select the table and mappings as described above. + +### Ingesting directly into the event tables from Azure Stream Analytics + +If you are using Azure Stream Analytics to pre-process the data from the Event Hub +or Event Stream, you can push the event data directly into the event tables. + +1. In the Azure portal, navigate to the Azure Stream Analytics job that you have + set up to process the data from the Event Hub or Event Stream. +2. In the job's "Overview" pane, click on the "Outputs" tab and add a new output +3. Select "Azure Data Explorer" as the output type. +4. Configure the output with the connection string of the Azure Data Explorer + cluster and the database name. +5. In the "Table" field, enter the name of the event table you want to target. + +In the "Query" field, you can use the `SELECT` statement to map the incoming +data to the table schema, filtered by `type`. For example: + +```sql +SELECT + data.*, + type as ___type, + source as ___source, + id as ___id, + time as ___time, + subject as ___subject +INTO + Trips +FROM + input_stream +WHERE + specversion = '1.0' AND type = 'GeneralTransitFeedStatic.Trips' +``` + diff --git a/gtfs/CONTAINER.md b/gtfs/CONTAINER.md index 500ea5c..7c7d4e1 100644 --- a/gtfs/CONTAINER.md +++ b/gtfs/CONTAINER.md @@ -32,6 +32,12 @@ Use as base image in Dockerfile: FROM ghcr.io/clemensv/real-time-sources-gtfs:latest ``` +## Database Schemas and handling + +If you want to build a full data pipeline with all events ingested into +database, the integration with Fabric Eventhouse and Azure Data Explorer is +described in [DATABASE.md](../DATABASE.md). + ## Using the container image The container image defines a single command that starts the bridge. The bridge diff --git a/gtfs/gtfs_rt_bridge/src/gtfs_rt_bridge/gtfs_cli.py b/gtfs/gtfs_rt_bridge/src/gtfs_rt_bridge/gtfs_cli.py index acb64a1..f8154a8 100644 --- a/gtfs/gtfs_rt_bridge/src/gtfs_rt_bridge/gtfs_cli.py +++ b/gtfs/gtfs_rt_bridge/src/gtfs_rt_bridge/gtfs_cli.py @@ -107,7 +107,6 @@ logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) - def fetch_schedule_file(gtfs_url: str, mdb_source_id: str, gtfs_headers: List[List[str]], etag: str, cache_dir: str | None) -> Tuple[str, str]: """ Fetches the latest schedule file from the schedule URL if the file does not exist in the cache. @@ -1049,10 +1048,9 @@ async def feed_realtime_messages(agency_id: str, kafka_bootstrap_servers: str, k "linger.ms": 100, "retries": 5, "retry.backoff.ms": 1000, - "batch.size": (1024*1024)-512, - "compression.type": "gzip" + "batch.size": (1024*1024)-512 } - producer: Producer = Producer(kafka_config) + producer: Producer = Producer(kafka_config, logger=logger) gtfs_rt_producer = GeneralTransitFeedRealTimeEventProducer(producer, kafka_topic,cloudevents_mode) gtfs_static_producer = GeneralTransitFeedStaticEventProducer(producer, kafka_topic, cloudevents_mode) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/__init__.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/__init__.py index dee27db..c3bf7b1 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/__init__.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/__init__.py @@ -1,4 +1,4 @@ -from .generaltransitfeedstatic import agency, locationtype, wheelchairboarding, stops, faremedia, transfers, pickuptype, dropofftype, continuouspickup, continuousdropoff, timepoint, stoptimes, bookingrules, fareproducts, faretransferrules, pathways, shapes, locationgroupstores, translations, locationgeojson, serviceavailability, calendar, exceptiontype, calendardates, timeframes, fareattributes, levels, directionid, wheelchairaccessible, bikesallowed, trips, frequencies, routetype, routes, stopareas, attributions, feedinfo, locationgroups, routenetworks, areas, networks, farerules, farelegrules -from .generaltransitfeedrealtime import alert, trip, vehicle +from .generaltransitfeedstatic import bookingrules, fareproducts, locationtype, wheelchairboarding, stops, pathways, serviceavailability, calendar, exceptiontype, calendardates, timeframes, stopareas, fareattributes, locationgroups, pickuptype, dropofftype, continuouspickup, continuousdropoff, timepoint, stoptimes, faremedia, faretransferrules, locationgeojson, transfers, levels, frequencies, directionid, wheelchairaccessible, bikesallowed, trips, farelegrules, attributions, routenetworks, shapes, agency, locationgroupstores, areas, routetype, routes, networks, farerules, translations, feedinfo +from .generaltransitfeedrealtime import trip, alert, vehicle -__all__ = ["agency", "locationtype", "wheelchairboarding", "stops", "faremedia", "transfers", "pickuptype", "dropofftype", "continuouspickup", "continuousdropoff", "timepoint", "stoptimes", "bookingrules", "fareproducts", "faretransferrules", "pathways", "shapes", "locationgroupstores", "translations", "locationgeojson", "serviceavailability", "calendar", "exceptiontype", "calendardates", "timeframes", "fareattributes", "levels", "directionid", "wheelchairaccessible", "bikesallowed", "trips", "frequencies", "routetype", "routes", "stopareas", "attributions", "feedinfo", "locationgroups", "routenetworks", "areas", "networks", "farerules", "farelegrules", "alert", "trip", "vehicle"] +__all__ = ["bookingrules", "fareproducts", "locationtype", "wheelchairboarding", "stops", "pathways", "serviceavailability", "calendar", "exceptiontype", "calendardates", "timeframes", "stopareas", "fareattributes", "locationgroups", "pickuptype", "dropofftype", "continuouspickup", "continuousdropoff", "timepoint", "stoptimes", "faremedia", "faretransferrules", "locationgeojson", "transfers", "levels", "frequencies", "directionid", "wheelchairaccessible", "bikesallowed", "trips", "farelegrules", "attributions", "routenetworks", "shapes", "agency", "locationgroupstores", "areas", "routetype", "routes", "networks", "farerules", "translations", "feedinfo", "trip", "alert", "vehicle"] diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/__init__.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/__init__.py index 6e3d67b..2f3a8e9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/__init__.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/__init__.py @@ -1,5 +1,5 @@ -from .alert import timerange, tripdescriptor_types, tripdescriptor, entityselector, alert_types, translatedstring_types, translatedstring, alert from .trip import tripdescriptor_types, tripdescriptor, vehicledescriptor, tripupdate_types, tripupdate +from .alert import timerange, tripdescriptor_types, tripdescriptor, entityselector, alert_types, translatedstring_types, translatedstring, alert from .vehicle import tripdescriptor_types, tripdescriptor, vehicledescriptor, position, vehicleposition_types, vehicleposition -__all__ = ["timerange", "tripdescriptor_types", "tripdescriptor", "entityselector", "alert_types", "translatedstring_types", "translatedstring", "alert", "tripdescriptor_types", "tripdescriptor", "vehicledescriptor", "tripupdate_types", "tripupdate", "tripdescriptor_types", "tripdescriptor", "vehicledescriptor", "position", "vehicleposition_types", "vehicleposition"] +__all__ = ["tripdescriptor_types", "tripdescriptor", "vehicledescriptor", "tripupdate_types", "tripupdate", "timerange", "tripdescriptor_types", "tripdescriptor", "entityselector", "alert_types", "translatedstring_types", "translatedstring", "alert", "tripdescriptor_types", "tripdescriptor", "vehicledescriptor", "position", "vehicleposition_types", "vehicleposition"] diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/alert.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/alert.py index 68cbb2d..82b2082 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/alert.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/alert.py @@ -8,10 +8,10 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.entityselector import EntitySelector +from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.alert_types.cause import Cause from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.alert_types.effect import Effect from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.timerange import TimeRange -from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.alert_types.cause import Cause +from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.entityselector import EntitySelector from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.translatedstring import TranslatedString @@ -35,7 +35,7 @@ class Alert: effect: typing.Optional[Effect]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="effect")) url: typing.Optional[TranslatedString]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="url")) header_text: typing.Optional[TranslatedString]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="header_text")) - description_text: typing.Optional[TranslatedString]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="description_text")) + description_text: typing.Optional[TranslatedString]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="description_text")) def __post_init__(self): @@ -100,7 +100,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/entityselector.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/entityselector.py index a3d273a..aa94d02 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/entityselector.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/entityselector.py @@ -27,7 +27,7 @@ class EntitySelector: route_id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="route_id")) route_type: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="route_type")) trip: typing.Optional[TripDescriptor]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="trip")) - stop_id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stop_id")) + stop_id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stop_id")) def __post_init__(self): @@ -90,7 +90,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/timerange.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/timerange.py index 165d7ab..975b02e 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/timerange.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/timerange.py @@ -20,7 +20,7 @@ class TimeRange: end (typing.Optional[int]): End time, in POSIX time (i.e., number of seconds since January 1st 1970 00:00:00 UTC). If missing, the interval ends at plus infinity.""" start: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start")) - end: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="end")) + end: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="end")) def __post_init__(self): @@ -80,7 +80,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring.py index dd90c3e..a5dfad0 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring.py @@ -19,7 +19,7 @@ class TranslatedString: Attributes: translation (typing.List[Translation]): At least one translation must be provided.""" - translation: typing.List[Translation]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="translation")) + translation: typing.List[Translation]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="translation")) def __post_init__(self): @@ -78,7 +78,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring_types/translation.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring_types/translation.py index 88256ed..27506f2 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring_types/translation.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/translatedstring_types/translation.py @@ -20,7 +20,7 @@ class Translation: language (typing.Optional[str]): BCP-47 language code. Can be omitted if the language is unknown or if no i18n is done at all for the feed. At most one translation is allowed to have an unspecified language tag.""" text: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="text")) - language: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="language")) + language: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="language")) def __post_init__(self): @@ -80,7 +80,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/tripdescriptor.py index 50e00ed..90903d2 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/alert/tripdescriptor.py @@ -29,7 +29,7 @@ class TripDescriptor: direction_id: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="direction_id")) start_time: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_time")) start_date: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_date")) - schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) + schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) def __post_init__(self): @@ -93,7 +93,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripdescriptor.py index 20b9f24..26153dc 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripdescriptor.py @@ -29,7 +29,7 @@ class TripDescriptor: direction_id: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="direction_id")) start_time: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_time")) start_date: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_date")) - schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) + schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) def __post_init__(self): @@ -93,7 +93,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate.py index 238e2c5..ea36c0a 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate.py @@ -8,9 +8,9 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.vehicledescriptor import VehicleDescriptor -from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeupdate import StopTimeUpdate from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripdescriptor import TripDescriptor +from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeupdate import StopTimeUpdate +from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.vehicledescriptor import VehicleDescriptor @dataclasses_json.dataclass_json @@ -29,7 +29,7 @@ class TripUpdate: vehicle: typing.Optional[VehicleDescriptor]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="vehicle")) stop_time_update: typing.List[StopTimeUpdate]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stop_time_update")) timestamp: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timestamp")) - delay: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="delay")) + delay: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="delay")) def __post_init__(self): @@ -93,7 +93,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeevent.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeevent.py index eb96bd6..d2ad956 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeevent.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeevent.py @@ -22,7 +22,7 @@ class StopTimeEvent: delay: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="delay")) time: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="time")) - uncertainty: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="uncertainty")) + uncertainty: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="uncertainty")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeupdate.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeupdate.py index 7f8f2a7..74395b7 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeupdate.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/tripupdate_types/stoptimeupdate.py @@ -8,8 +8,8 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeevent import StopTimeEvent from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeupdate_types.schedulerelationship import ScheduleRelationship +from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeevent import StopTimeEvent @dataclasses_json.dataclass_json @@ -28,7 +28,7 @@ class StopTimeUpdate: stop_id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stop_id")) arrival: typing.Optional[StopTimeEvent]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="arrival")) departure: typing.Optional[StopTimeEvent]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="departure")) - schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) + schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) def __post_init__(self): @@ -91,7 +91,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/vehicledescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/vehicledescriptor.py index 6b0c308..b2b6c1b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/vehicledescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/trip/vehicledescriptor.py @@ -22,7 +22,7 @@ class VehicleDescriptor: id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="id")) label: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="label")) - license_plate: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="license_plate")) + license_plate: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="license_plate")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/position.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/position.py index 707d7ea..0839135 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/position.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/position.py @@ -26,7 +26,7 @@ class Position: longitude: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="longitude")) bearing: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bearing")) odometer: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="odometer")) - speed: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="speed")) + speed: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="speed")) def __post_init__(self): @@ -89,7 +89,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/tripdescriptor.py index 739868c..2decf10 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/tripdescriptor.py @@ -29,7 +29,7 @@ class TripDescriptor: direction_id: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="direction_id")) start_time: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_time")) start_date: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="start_date")) - schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) + schedule_relationship: typing.Optional[ScheduleRelationship]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="schedule_relationship")) def __post_init__(self): @@ -93,7 +93,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicledescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicledescriptor.py index 6b0c308..b2b6c1b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicledescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicledescriptor.py @@ -22,7 +22,7 @@ class VehicleDescriptor: id: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="id")) label: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="label")) - license_plate: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="license_plate")) + license_plate: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="license_plate")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicleposition.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicleposition.py index 0700690..c3fb53c 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicleposition.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedrealtime/vehicle/vehicleposition.py @@ -9,10 +9,10 @@ import dataclasses_json import json from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicleposition_types.congestionlevel import CongestionLevel +from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicledescriptor import VehicleDescriptor from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.tripdescriptor import TripDescriptor from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicleposition_types.occupancystatus import OccupancyStatus from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicleposition_types.vehiclestopstatus import VehicleStopStatus -from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicledescriptor import VehicleDescriptor from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.position import Position @@ -40,7 +40,7 @@ class VehiclePosition: current_status: typing.Optional[VehicleStopStatus]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="current_status")) timestamp: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timestamp")) congestion_level: typing.Optional[CongestionLevel]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="congestion_level")) - occupancy_status: typing.Optional[OccupancyStatus]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="occupancy_status")) + occupancy_status: typing.Optional[OccupancyStatus]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="occupancy_status")) def __post_init__(self): @@ -107,7 +107,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/__init__.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/__init__.py index 1ec496e..deafcc1 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/__init__.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/__init__.py @@ -1,45 +1,45 @@ -from .agency import Agency +from .bookingrules import BookingRules +from .fareproducts import FareProducts from .locationtype import LocationType from .wheelchairboarding import WheelchairBoarding from .stops import Stops -from .faremedia import FareMedia -from .transfers import Transfers +from .pathways import Pathways +from .serviceavailability import ServiceAvailability +from .calendar import Calendar +from .exceptiontype import ExceptionType +from .calendardates import CalendarDates +from .timeframes import Timeframes +from .stopareas import StopAreas +from .fareattributes import FareAttributes +from .locationgroups import LocationGroups from .pickuptype import PickupType from .dropofftype import DropOffType from .continuouspickup import ContinuousPickup from .continuousdropoff import ContinuousDropOff from .timepoint import Timepoint from .stoptimes import StopTimes -from .bookingrules import BookingRules -from .fareproducts import FareProducts +from .faremedia import FareMedia from .faretransferrules import FareTransferRules -from .pathways import Pathways -from .shapes import Shapes -from .locationgroupstores import LocationGroupStores -from .translations import Translations from .locationgeojson import LocationGeoJson -from .serviceavailability import ServiceAvailability -from .calendar import Calendar -from .exceptiontype import ExceptionType -from .calendardates import CalendarDates -from .timeframes import Timeframes -from .fareattributes import FareAttributes +from .transfers import Transfers from .levels import Levels +from .frequencies import Frequencies from .directionid import DirectionId from .wheelchairaccessible import WheelchairAccessible from .bikesallowed import BikesAllowed from .trips import Trips -from .frequencies import Frequencies -from .routetype import RouteType -from .routes import Routes -from .stopareas import StopAreas +from .farelegrules import FareLegRules from .attributions import Attributions -from .feedinfo import FeedInfo -from .locationgroups import LocationGroups from .routenetworks import RouteNetworks +from .shapes import Shapes +from .agency import Agency +from .locationgroupstores import LocationGroupStores from .areas import Areas +from .routetype import RouteType +from .routes import Routes from .networks import Networks from .farerules import FareRules -from .farelegrules import FareLegRules +from .translations import Translations +from .feedinfo import FeedInfo -__all__ = ["Agency", "LocationType", "WheelchairBoarding", "Stops", "FareMedia", "Transfers", "PickupType", "DropOffType", "ContinuousPickup", "ContinuousDropOff", "Timepoint", "StopTimes", "BookingRules", "FareProducts", "FareTransferRules", "Pathways", "Shapes", "LocationGroupStores", "Translations", "LocationGeoJson", "ServiceAvailability", "Calendar", "ExceptionType", "CalendarDates", "Timeframes", "FareAttributes", "Levels", "DirectionId", "WheelchairAccessible", "BikesAllowed", "Trips", "Frequencies", "RouteType", "Routes", "StopAreas", "Attributions", "FeedInfo", "LocationGroups", "RouteNetworks", "Areas", "Networks", "FareRules", "FareLegRules"] +__all__ = ["BookingRules", "FareProducts", "LocationType", "WheelchairBoarding", "Stops", "Pathways", "ServiceAvailability", "Calendar", "ExceptionType", "CalendarDates", "Timeframes", "StopAreas", "FareAttributes", "LocationGroups", "PickupType", "DropOffType", "ContinuousPickup", "ContinuousDropOff", "Timepoint", "StopTimes", "FareMedia", "FareTransferRules", "LocationGeoJson", "Transfers", "Levels", "Frequencies", "DirectionId", "WheelchairAccessible", "BikesAllowed", "Trips", "FareLegRules", "Attributions", "RouteNetworks", "Shapes", "Agency", "LocationGroupStores", "Areas", "RouteType", "Routes", "Networks", "FareRules", "Translations", "FeedInfo"] diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/agency.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/agency.py index 4cf5793..2b88a55 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/agency.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/agency.py @@ -32,7 +32,7 @@ class Agency: agencyLang: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyLang")) agencyPhone: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyPhone")) agencyFareUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyFareUrl")) - agencyEmail: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyEmail")) + agencyEmail: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyEmail")) def __post_init__(self): @@ -98,7 +98,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/areas.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/areas.py index 0b81bad..8b4ea6c 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/areas.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/areas.py @@ -24,7 +24,7 @@ class Areas: areaId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaId")) areaName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaName")) areaDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaDesc")) - areaUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaUrl")) + areaUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/attributions.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/attributions.py index 4cddbc1..47ad73f 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/attributions.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/attributions.py @@ -38,7 +38,7 @@ class Attributions: isAuthority: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="isAuthority")) attributionUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="attributionUrl")) attributionEmail: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="attributionEmail")) - attributionPhone: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="attributionPhone")) + attributionPhone: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="attributionPhone")) def __post_init__(self): @@ -107,7 +107,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/bookingrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/bookingrules.py index b96ed3c..8153388 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/bookingrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/bookingrules.py @@ -24,7 +24,7 @@ class BookingRules: bookingRuleId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bookingRuleId")) bookingRuleName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bookingRuleName")) bookingRuleDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bookingRuleDesc")) - bookingRuleUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bookingRuleUrl")) + bookingRuleUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bookingRuleUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendar.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendar.py index 725bfca..c8ee07b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendar.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendar.py @@ -37,7 +37,7 @@ class Calendar: saturday: ServiceAvailability=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="saturday")) sunday: ServiceAvailability=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="sunday")) startDate: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="startDate")) - endDate: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="endDate")) + endDate: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="endDate")) def __post_init__(self): @@ -105,7 +105,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendardates.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendardates.py index dbfe091..200fe66 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendardates.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/calendardates.py @@ -23,7 +23,7 @@ class CalendarDates: serviceId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="serviceId")) date: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="date")) - exceptionType: ExceptionType=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="exceptionType")) + exceptionType: ExceptionType=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="exceptionType")) def __post_init__(self): @@ -84,7 +84,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareattributes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareattributes.py index e6d4bb2..80b5596 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareattributes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareattributes.py @@ -30,7 +30,7 @@ class FareAttributes: paymentMethod: int=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="paymentMethod")) transfers: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="transfers")) agencyId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agencyId")) - transferDuration: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="transferDuration")) + transferDuration: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="transferDuration")) def __post_init__(self): @@ -95,7 +95,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farelegrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farelegrules.py index 3a173e3..ebba70e 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farelegrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farelegrules.py @@ -28,7 +28,7 @@ class FareLegRules: legGroupId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="legGroupId")) networkId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) fromAreaId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fromAreaId")) - toAreaId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="toAreaId")) + toAreaId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="toAreaId")) def __post_init__(self): @@ -92,7 +92,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faremedia.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faremedia.py index acf70f1..eafaf99 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faremedia.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faremedia.py @@ -24,7 +24,7 @@ class FareMedia: fareMediaId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareMediaId")) fareMediaName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareMediaName")) fareMediaDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareMediaDesc")) - fareMediaUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareMediaUrl")) + fareMediaUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareMediaUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareproducts.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareproducts.py index fde1df0..b773fde 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareproducts.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/fareproducts.py @@ -24,7 +24,7 @@ class FareProducts: fareProductId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareProductId")) fareProductName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareProductName")) fareProductDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareProductDesc")) - fareProductUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareProductUrl")) + fareProductUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fareProductUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farerules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farerules.py index f03ff71..4a3d188 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farerules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/farerules.py @@ -26,7 +26,7 @@ class FareRules: routeId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="routeId")) originId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="originId")) destinationId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="destinationId")) - containsId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="containsId")) + containsId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="containsId")) def __post_init__(self): @@ -89,7 +89,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faretransferrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faretransferrules.py index 6c20cf0..710158b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faretransferrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/faretransferrules.py @@ -30,7 +30,7 @@ class FareTransferRules: fromLegGroupId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fromLegGroupId")) toLegGroupId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="toLegGroupId")) duration: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="duration")) - durationType: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="durationType")) + durationType: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="durationType")) def __post_init__(self): @@ -95,7 +95,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/feedinfo.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/feedinfo.py index 9a1a8bf..55280ae 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/feedinfo.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/feedinfo.py @@ -34,7 +34,7 @@ class FeedInfo: feedEndDate: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="feedEndDate")) feedVersion: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="feedVersion")) feedContactEmail: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="feedContactEmail")) - feedContactUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="feedContactUrl")) + feedContactUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="feedContactUrl")) def __post_init__(self): @@ -101,7 +101,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/frequencies.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/frequencies.py index 414708b..f4cb8d1 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/frequencies.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/frequencies.py @@ -26,7 +26,7 @@ class Frequencies: startTime: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="startTime")) endTime: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="endTime")) headwaySecs: int=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="headwaySecs")) - exactTimes: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="exactTimes")) + exactTimes: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="exactTimes")) def __post_init__(self): @@ -89,7 +89,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/levels.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/levels.py index e36b7c3..1f1db60 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/levels.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/levels.py @@ -22,7 +22,7 @@ class Levels: levelId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="levelId")) levelIndex: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="levelIndex")) - levelName: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="levelName")) + levelName: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="levelName")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgeojson.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgeojson.py index d038868..53a2eb2 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgeojson.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgeojson.py @@ -22,7 +22,7 @@ class LocationGeoJson: locationGeoJsonId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGeoJsonId")) locationGeoJsonType: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGeoJsonType")) - locationGeoJsonData: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGeoJsonData")) + locationGeoJsonData: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGeoJsonData")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroups.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroups.py index a814ee0..4ca5baa 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroups.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroups.py @@ -24,7 +24,7 @@ class LocationGroups: locationGroupId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupId")) locationGroupName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupName")) locationGroupDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupDesc")) - locationGroupUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupUrl")) + locationGroupUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroupstores.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroupstores.py index e72b717..961a2c4 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroupstores.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/locationgroupstores.py @@ -22,7 +22,7 @@ class LocationGroupStores: locationGroupStoreId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupStoreId")) locationGroupId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="locationGroupId")) - storeId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="storeId")) + storeId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="storeId")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/networks.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/networks.py index 88961a4..75ce357 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/networks.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/networks.py @@ -24,7 +24,7 @@ class Networks: networkId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) networkName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkName")) networkDesc: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkDesc")) - networkUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkUrl")) + networkUrl: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkUrl")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/pathways.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/pathways.py index 1d5af5f..0e31b1b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/pathways.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/pathways.py @@ -40,7 +40,7 @@ class Pathways: maxSlope: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="maxSlope")) minWidth: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="minWidth")) signpostedAs: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="signpostedAs")) - reversedSignpostedAs: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="reversedSignpostedAs")) + reversedSignpostedAs: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="reversedSignpostedAs")) def __post_init__(self): @@ -110,7 +110,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routenetworks.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routenetworks.py index 4f793eb..9bf93c7 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routenetworks.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routenetworks.py @@ -22,7 +22,7 @@ class RouteNetworks: routeNetworkId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="routeNetworkId")) routeId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="routeId")) - networkId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) + networkId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routes.py index db6abef..04705b1 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/routes.py @@ -8,8 +8,8 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedstatic.routetype import RouteType from gtfs_rt_producer_data.generaltransitfeedstatic.continuousdropoff import ContinuousDropOff +from gtfs_rt_producer_data.generaltransitfeedstatic.routetype import RouteType from gtfs_rt_producer_data.generaltransitfeedstatic.continuouspickup import ContinuousPickup @@ -45,7 +45,7 @@ class Routes: routeSortOrder: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="routeSortOrder")) continuousPickup: ContinuousPickup=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="continuousPickup")) continuousDropOff: ContinuousDropOff=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="continuousDropOff")) - networkId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) + networkId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="networkId")) def __post_init__(self): @@ -116,7 +116,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/shapes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/shapes.py index 7bd825c..d31aea3 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/shapes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/shapes.py @@ -26,7 +26,7 @@ class Shapes: shapePtLat: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapePtLat")) shapePtLon: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapePtLon")) shapePtSequence: int=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapePtSequence")) - shapeDistTraveled: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapeDistTraveled")) + shapeDistTraveled: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapeDistTraveled")) def __post_init__(self): @@ -89,7 +89,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stopareas.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stopareas.py index 3f83899..9f504fb 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stopareas.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stopareas.py @@ -22,7 +22,7 @@ class StopAreas: stopAreaId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stopAreaId")) stopId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stopId")) - areaId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaId")) + areaId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="areaId")) def __post_init__(self): @@ -83,7 +83,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stops.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stops.py index fb08dc1..e5403a8 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stops.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stops.py @@ -8,8 +8,8 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedstatic.locationtype import LocationType from gtfs_rt_producer_data.generaltransitfeedstatic.wheelchairboarding import WheelchairBoarding +from gtfs_rt_producer_data.generaltransitfeedstatic.locationtype import LocationType @dataclasses_json.dataclass_json @@ -48,7 +48,7 @@ class Stops: stopTimezone: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stopTimezone")) wheelchairBoarding: WheelchairBoarding=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="wheelchairBoarding")) levelId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="levelId")) - platformCode: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="platformCode")) + platformCode: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="platformCode")) def __post_init__(self): @@ -121,7 +121,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stoptimes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stoptimes.py index 283146b..f2a3552 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stoptimes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/stoptimes.py @@ -8,9 +8,9 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedstatic.continuousdropoff import ContinuousDropOff from gtfs_rt_producer_data.generaltransitfeedstatic.timepoint import Timepoint from gtfs_rt_producer_data.generaltransitfeedstatic.pickuptype import PickupType +from gtfs_rt_producer_data.generaltransitfeedstatic.continuousdropoff import ContinuousDropOff from gtfs_rt_producer_data.generaltransitfeedstatic.dropofftype import DropOffType from gtfs_rt_producer_data.generaltransitfeedstatic.continuouspickup import ContinuousPickup @@ -45,7 +45,7 @@ class StopTimes: continuousPickup: typing.Optional[ContinuousPickup]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="continuousPickup")) continuousDropOff: typing.Optional[ContinuousDropOff]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="continuousDropOff")) shapeDistTraveled: typing.Optional[float]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapeDistTraveled")) - timepoint: Timepoint=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timepoint")) + timepoint: Timepoint=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timepoint")) def __post_init__(self): @@ -115,7 +115,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/timeframes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/timeframes.py index f3d2edc..c9d18a5 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/timeframes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/timeframes.py @@ -26,7 +26,7 @@ class Timeframes: timeframeGroupId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timeframeGroupId")) startTime: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="startTime")) endTime: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="endTime")) - serviceDates: typing.Union[Calendar, CalendarDates]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="serviceDates")) + serviceDates: typing.Union[Calendar, CalendarDates]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="serviceDates")) def __post_init__(self): @@ -88,7 +88,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/transfers.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/transfers.py index 75571a6..cfc7994 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/transfers.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/transfers.py @@ -24,7 +24,7 @@ class Transfers: fromStopId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fromStopId")) toStopId: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="toStopId")) transferType: int=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="transferType")) - minTransferTime: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="minTransferTime")) + minTransferTime: typing.Optional[int]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="minTransferTime")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/translations.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/translations.py index 271ecf3..b310b1d 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/translations.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/translations.py @@ -24,7 +24,7 @@ class Translations: tableName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="tableName")) fieldName: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="fieldName")) language: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="language")) - translation: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="translation")) + translation: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="translation")) def __post_init__(self): @@ -86,7 +86,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/trips.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/trips.py index 5582cb7..3112e92 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/trips.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/src/gtfs_rt_producer_data/generaltransitfeedstatic/trips.py @@ -8,11 +8,11 @@ import dataclasses import dataclasses_json import json -from gtfs_rt_producer_data.generaltransitfeedstatic.calendar import Calendar -from gtfs_rt_producer_data.generaltransitfeedstatic.calendardates import CalendarDates from gtfs_rt_producer_data.generaltransitfeedstatic.wheelchairaccessible import WheelchairAccessible +from gtfs_rt_producer_data.generaltransitfeedstatic.calendar import Calendar from gtfs_rt_producer_data.generaltransitfeedstatic.directionid import DirectionId from gtfs_rt_producer_data.generaltransitfeedstatic.bikesallowed import BikesAllowed +from gtfs_rt_producer_data.generaltransitfeedstatic.calendardates import CalendarDates @dataclasses_json.dataclass_json @@ -43,7 +43,7 @@ class Trips: blockId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="blockId")) shapeId: typing.Optional[str]=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shapeId")) wheelchairAccessible: WheelchairAccessible=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="wheelchairAccessible")) - bikesAllowed: BikesAllowed=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bikesAllowed")) + bikesAllowed: BikesAllowed=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="bikesAllowed")) def __post_init__(self): @@ -113,7 +113,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert.py index 6fb8042..dba7403 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert.py @@ -9,12 +9,13 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.alert import Alert -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector import Test_EntitySelector +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert_types_cause import Test_Cause from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert_types_effect import Test_Effect from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_timerange import Test_TimeRange -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_alert_types_cause import Test_Cause +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector import Test_EntitySelector from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring import Test_TranslatedString + class Test_Alert(unittest.TestCase): """ Test case for Alert @@ -32,8 +33,8 @@ def create_instance(): Create instance of Alert for testing """ instance = Alert( - active_period=[Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance()], - informed_entity=[Test_EntitySelector.create_instance()], + active_period=[Test_TimeRange.create_instance(), Test_TimeRange.create_instance()], + informed_entity=[Test_EntitySelector.create_instance(), Test_EntitySelector.create_instance()], cause=Test_Cause.create_instance(), effect=Test_Effect.create_instance(), url=Test_TranslatedString.create_instance(), @@ -47,7 +48,7 @@ def test_active_period_property(self): """ Test active_period property """ - test_value = [Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance(), Test_TimeRange.create_instance()] + test_value = [Test_TimeRange.create_instance(), Test_TimeRange.create_instance()] self.instance.active_period = test_value self.assertEqual(self.instance.active_period, test_value) @@ -55,7 +56,7 @@ def test_informed_entity_property(self): """ Test informed_entity property """ - test_value = [Test_EntitySelector.create_instance()] + test_value = [Test_EntitySelector.create_instance(), Test_EntitySelector.create_instance()] self.instance.informed_entity = test_value self.assertEqual(self.instance.informed_entity, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector.py index a6b7547..b41c26f 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_entityselector.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.entityselector import EntitySelector from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor import Test_TripDescriptor + class Test_EntitySelector(unittest.TestCase): """ Test case for EntitySelector @@ -28,11 +29,11 @@ def create_instance(): Create instance of EntitySelector for testing """ instance = EntitySelector( - agency_id='lszsmxfbnhhvccyoqfjm', - route_id='tfefgldayootbvenduxj', - route_type=int(30), + agency_id='gxcnksmgblqlynmibyyf', + route_id='pjhgaszrnyggundlzldl', + route_type=int(81), trip=Test_TripDescriptor.create_instance(), - stop_id='kisllbnvcmtutgojincv' + stop_id='ivuadfbbmpwgjzbxoavh' ) return instance @@ -41,7 +42,7 @@ def test_agency_id_property(self): """ Test agency_id property """ - test_value = 'lszsmxfbnhhvccyoqfjm' + test_value = 'gxcnksmgblqlynmibyyf' self.instance.agency_id = test_value self.assertEqual(self.instance.agency_id, test_value) @@ -49,7 +50,7 @@ def test_route_id_property(self): """ Test route_id property """ - test_value = 'tfefgldayootbvenduxj' + test_value = 'pjhgaszrnyggundlzldl' self.instance.route_id = test_value self.assertEqual(self.instance.route_id, test_value) @@ -57,7 +58,7 @@ def test_route_type_property(self): """ Test route_type property """ - test_value = int(30) + test_value = int(81) self.instance.route_type = test_value self.assertEqual(self.instance.route_type, test_value) @@ -73,7 +74,7 @@ def test_stop_id_property(self): """ Test stop_id property """ - test_value = 'kisllbnvcmtutgojincv' + test_value = 'ivuadfbbmpwgjzbxoavh' self.instance.stop_id = test_value self.assertEqual(self.instance.stop_id, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_timerange.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_timerange.py index 01ba3c5..72ecf77 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_timerange.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_timerange.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.timerange import TimeRange + class Test_TimeRange(unittest.TestCase): """ Test case for TimeRange @@ -27,8 +28,8 @@ def create_instance(): Create instance of TimeRange for testing """ instance = TimeRange( - start=int(66), - end=int(89) + start=int(39), + end=int(4) ) return instance @@ -37,7 +38,7 @@ def test_start_property(self): """ Test start property """ - test_value = int(66) + test_value = int(39) self.instance.start = test_value self.assertEqual(self.instance.start, test_value) @@ -45,7 +46,7 @@ def test_end_property(self): """ Test end property """ - test_value = int(89) + test_value = int(4) self.instance.end = test_value self.assertEqual(self.instance.end, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring.py index 5c189e0..bad35bb 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.translatedstring import TranslatedString from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring_types_translation import Test_Translation + class Test_TranslatedString(unittest.TestCase): """ Test case for TranslatedString @@ -28,7 +29,7 @@ def create_instance(): Create instance of TranslatedString for testing """ instance = TranslatedString( - translation=[Test_Translation.create_instance()] + translation=[Test_Translation.create_instance(), Test_Translation.create_instance(), Test_Translation.create_instance()] ) return instance @@ -37,7 +38,7 @@ def test_translation_property(self): """ Test translation property """ - test_value = [Test_Translation.create_instance()] + test_value = [Test_Translation.create_instance(), Test_Translation.create_instance(), Test_Translation.create_instance()] self.instance.translation = test_value self.assertEqual(self.instance.translation, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring_types_translation.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring_types_translation.py index 392d754..3eacd65 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring_types_translation.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_translatedstring_types_translation.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.translatedstring_types.translation import Translation + class Test_Translation(unittest.TestCase): """ Test case for Translation @@ -27,8 +28,8 @@ def create_instance(): Create instance of Translation for testing """ instance = Translation( - text='rmeprxytceqskgixpcho', - language='vqlrutmqpsdpoxltxqfp' + text='fyaudzmlmrtsxjpufzel', + language='dtszasjvkliuszcfwkzi' ) return instance @@ -37,7 +38,7 @@ def test_text_property(self): """ Test text property """ - test_value = 'rmeprxytceqskgixpcho' + test_value = 'fyaudzmlmrtsxjpufzel' self.instance.text = test_value self.assertEqual(self.instance.text, test_value) @@ -45,7 +46,7 @@ def test_language_property(self): """ Test language property """ - test_value = 'vqlrutmqpsdpoxltxqfp' + test_value = 'dtszasjvkliuszcfwkzi' self.instance.language = test_value self.assertEqual(self.instance.language, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor.py index b7668f9..ecd39b9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.alert.tripdescriptor import TripDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_alert_tripdescriptor_types_schedulerelationship import Test_ScheduleRelationship + class Test_TripDescriptor(unittest.TestCase): """ Test case for TripDescriptor @@ -28,11 +29,11 @@ def create_instance(): Create instance of TripDescriptor for testing """ instance = TripDescriptor( - trip_id='qglsupoexwacuytlexbk', - route_id='jxpiqhkvbyozrnsecluk', - direction_id=int(85), - start_time='kwzqdkixaqlogxptlato', - start_date='leqhbdjoqzhbtwnptzxd', + trip_id='dtvpysbcfhhlafjfjrkv', + route_id='ilbzppzemojihpcjzhiw', + direction_id=int(26), + start_time='hehbuquskidywfcuaqys', + start_date='evlumeaomjaqbrgpydjw', schedule_relationship=Test_ScheduleRelationship.create_instance() ) return instance @@ -42,7 +43,7 @@ def test_trip_id_property(self): """ Test trip_id property """ - test_value = 'qglsupoexwacuytlexbk' + test_value = 'dtvpysbcfhhlafjfjrkv' self.instance.trip_id = test_value self.assertEqual(self.instance.trip_id, test_value) @@ -50,7 +51,7 @@ def test_route_id_property(self): """ Test route_id property """ - test_value = 'jxpiqhkvbyozrnsecluk' + test_value = 'ilbzppzemojihpcjzhiw' self.instance.route_id = test_value self.assertEqual(self.instance.route_id, test_value) @@ -58,7 +59,7 @@ def test_direction_id_property(self): """ Test direction_id property """ - test_value = int(85) + test_value = int(26) self.instance.direction_id = test_value self.assertEqual(self.instance.direction_id, test_value) @@ -66,7 +67,7 @@ def test_start_time_property(self): """ Test start_time property """ - test_value = 'kwzqdkixaqlogxptlato' + test_value = 'hehbuquskidywfcuaqys' self.instance.start_time = test_value self.assertEqual(self.instance.start_time, test_value) @@ -74,7 +75,7 @@ def test_start_date_property(self): """ Test start_date property """ - test_value = 'leqhbdjoqzhbtwnptzxd' + test_value = 'evlumeaomjaqbrgpydjw' self.instance.start_date = test_value self.assertEqual(self.instance.start_date, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor.py index 5099fbc..94d7207 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripdescriptor import TripDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor_types_schedulerelationship import Test_ScheduleRelationship + class Test_TripDescriptor(unittest.TestCase): """ Test case for TripDescriptor @@ -28,11 +29,11 @@ def create_instance(): Create instance of TripDescriptor for testing """ instance = TripDescriptor( - trip_id='lsgpttqfanckpgtseveb', - route_id='thxjemzilbovxjncgzio', - direction_id=int(26), - start_time='ogxjzkildrujoydterqd', - start_date='cfqeiseacbwrszivpyeb', + trip_id='exlfkflxzdftsmiuuslf', + route_id='pnqrrjzenysnxdcbuhhv', + direction_id=int(35), + start_time='hlqtxokxhzjmaiyxcsix', + start_date='ittpkxlmbsknyaoroila', schedule_relationship=Test_ScheduleRelationship.create_instance() ) return instance @@ -42,7 +43,7 @@ def test_trip_id_property(self): """ Test trip_id property """ - test_value = 'lsgpttqfanckpgtseveb' + test_value = 'exlfkflxzdftsmiuuslf' self.instance.trip_id = test_value self.assertEqual(self.instance.trip_id, test_value) @@ -50,7 +51,7 @@ def test_route_id_property(self): """ Test route_id property """ - test_value = 'thxjemzilbovxjncgzio' + test_value = 'pnqrrjzenysnxdcbuhhv' self.instance.route_id = test_value self.assertEqual(self.instance.route_id, test_value) @@ -58,7 +59,7 @@ def test_direction_id_property(self): """ Test direction_id property """ - test_value = int(26) + test_value = int(35) self.instance.direction_id = test_value self.assertEqual(self.instance.direction_id, test_value) @@ -66,7 +67,7 @@ def test_start_time_property(self): """ Test start_time property """ - test_value = 'ogxjzkildrujoydterqd' + test_value = 'hlqtxokxhzjmaiyxcsix' self.instance.start_time = test_value self.assertEqual(self.instance.start_time, test_value) @@ -74,7 +75,7 @@ def test_start_date_property(self): """ Test start_date property """ - test_value = 'cfqeiseacbwrszivpyeb' + test_value = 'ittpkxlmbsknyaoroila' self.instance.start_date = test_value self.assertEqual(self.instance.start_date, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate.py index f28bef7..1fb2c1d 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate.py @@ -9,9 +9,10 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate import TripUpdate -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor import Test_VehicleDescriptor -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate import Test_StopTimeUpdate from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripdescriptor import Test_TripDescriptor +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate import Test_StopTimeUpdate +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor import Test_VehicleDescriptor + class Test_TripUpdate(unittest.TestCase): """ @@ -33,8 +34,8 @@ def create_instance(): trip=Test_TripDescriptor.create_instance(), vehicle=Test_VehicleDescriptor.create_instance(), stop_time_update=[Test_StopTimeUpdate.create_instance(), Test_StopTimeUpdate.create_instance(), Test_StopTimeUpdate.create_instance(), Test_StopTimeUpdate.create_instance(), Test_StopTimeUpdate.create_instance()], - timestamp=int(81), - delay=int(7) + timestamp=int(56), + delay=int(69) ) return instance @@ -67,7 +68,7 @@ def test_timestamp_property(self): """ Test timestamp property """ - test_value = int(81) + test_value = int(56) self.instance.timestamp = test_value self.assertEqual(self.instance.timestamp, test_value) @@ -75,7 +76,7 @@ def test_delay_property(self): """ Test delay property """ - test_value = int(7) + test_value = int(69) self.instance.delay = test_value self.assertEqual(self.instance.delay, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent.py index e11ecd8..866560a 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeevent import StopTimeEvent + class Test_StopTimeEvent(unittest.TestCase): """ Test case for StopTimeEvent @@ -27,9 +28,9 @@ def create_instance(): Create instance of StopTimeEvent for testing """ instance = StopTimeEvent( - delay=int(77), - time=int(73), - uncertainty=int(91) + delay=int(50), + time=int(44), + uncertainty=int(4) ) return instance @@ -38,7 +39,7 @@ def test_delay_property(self): """ Test delay property """ - test_value = int(77) + test_value = int(50) self.instance.delay = test_value self.assertEqual(self.instance.delay, test_value) @@ -46,7 +47,7 @@ def test_time_property(self): """ Test time property """ - test_value = int(73) + test_value = int(44) self.instance.time = test_value self.assertEqual(self.instance.time, test_value) @@ -54,7 +55,7 @@ def test_uncertainty_property(self): """ Test uncertainty property """ - test_value = int(91) + test_value = int(4) self.instance.uncertainty = test_value self.assertEqual(self.instance.uncertainty, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate.py index 76ed8b5..ad4a5da 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate.py @@ -9,8 +9,9 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.tripupdate_types.stoptimeupdate import StopTimeUpdate -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent import Test_StopTimeEvent from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeupdate_types_schedulerelationship import Test_ScheduleRelationship +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_tripupdate_types_stoptimeevent import Test_StopTimeEvent + class Test_StopTimeUpdate(unittest.TestCase): """ @@ -29,8 +30,8 @@ def create_instance(): Create instance of StopTimeUpdate for testing """ instance = StopTimeUpdate( - stop_sequence=int(77), - stop_id='mhadwyaehvdwpunlecmj', + stop_sequence=int(99), + stop_id='vzfroynyusdrmcgrqslj', arrival=Test_StopTimeEvent.create_instance(), departure=Test_StopTimeEvent.create_instance(), schedule_relationship=Test_ScheduleRelationship.create_instance() @@ -42,7 +43,7 @@ def test_stop_sequence_property(self): """ Test stop_sequence property """ - test_value = int(77) + test_value = int(99) self.instance.stop_sequence = test_value self.assertEqual(self.instance.stop_sequence, test_value) @@ -50,7 +51,7 @@ def test_stop_id_property(self): """ Test stop_id property """ - test_value = 'mhadwyaehvdwpunlecmj' + test_value = 'vzfroynyusdrmcgrqslj' self.instance.stop_id = test_value self.assertEqual(self.instance.stop_id, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor.py index 330032e..439cc3d 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_trip_vehicledescriptor.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.trip.vehicledescriptor import VehicleDescriptor + class Test_VehicleDescriptor(unittest.TestCase): """ Test case for VehicleDescriptor @@ -27,9 +28,9 @@ def create_instance(): Create instance of VehicleDescriptor for testing """ instance = VehicleDescriptor( - id='mhpdutwcrvmrjqkfzutr', - label='ziryuyksmevknkxgrswq', - license_plate='rpzkenkinlknbrojxtex' + id='loaflhgdmostltmohnqx', + label='egblyxgvvtdgxvennuej', + license_plate='vpbbrramckfrachdjcth' ) return instance @@ -38,7 +39,7 @@ def test_id_property(self): """ Test id property """ - test_value = 'mhpdutwcrvmrjqkfzutr' + test_value = 'loaflhgdmostltmohnqx' self.instance.id = test_value self.assertEqual(self.instance.id, test_value) @@ -46,7 +47,7 @@ def test_label_property(self): """ Test label property """ - test_value = 'ziryuyksmevknkxgrswq' + test_value = 'egblyxgvvtdgxvennuej' self.instance.label = test_value self.assertEqual(self.instance.label, test_value) @@ -54,7 +55,7 @@ def test_license_plate_property(self): """ Test license_plate property """ - test_value = 'rpzkenkinlknbrojxtex' + test_value = 'vpbbrramckfrachdjcth' self.instance.license_plate = test_value self.assertEqual(self.instance.license_plate, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_position.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_position.py index 6a43e39..bd0131a 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_position.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_position.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.position import Position + class Test_Position(unittest.TestCase): """ Test case for Position @@ -27,11 +28,11 @@ def create_instance(): Create instance of Position for testing """ instance = Position( - latitude=float(74.81703275295268), - longitude=float(54.87945296095138), - bearing=float(8.010107073749584), - odometer=float(54.652392261686266), - speed=float(82.25027282559265) + latitude=float(59.0878001952112), + longitude=float(89.51989918184016), + bearing=float(73.14224043422124), + odometer=float(74.87562365214251), + speed=float(29.87618498002088) ) return instance @@ -40,7 +41,7 @@ def test_latitude_property(self): """ Test latitude property """ - test_value = float(74.81703275295268) + test_value = float(59.0878001952112) self.instance.latitude = test_value self.assertEqual(self.instance.latitude, test_value) @@ -48,7 +49,7 @@ def test_longitude_property(self): """ Test longitude property """ - test_value = float(54.87945296095138) + test_value = float(89.51989918184016) self.instance.longitude = test_value self.assertEqual(self.instance.longitude, test_value) @@ -56,7 +57,7 @@ def test_bearing_property(self): """ Test bearing property """ - test_value = float(8.010107073749584) + test_value = float(73.14224043422124) self.instance.bearing = test_value self.assertEqual(self.instance.bearing, test_value) @@ -64,7 +65,7 @@ def test_odometer_property(self): """ Test odometer property """ - test_value = float(54.652392261686266) + test_value = float(74.87562365214251) self.instance.odometer = test_value self.assertEqual(self.instance.odometer, test_value) @@ -72,7 +73,7 @@ def test_speed_property(self): """ Test speed property """ - test_value = float(82.25027282559265) + test_value = float(29.87618498002088) self.instance.speed = test_value self.assertEqual(self.instance.speed, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor.py index 5a5558d..983c5b8 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.tripdescriptor import TripDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor_types_schedulerelationship import Test_ScheduleRelationship + class Test_TripDescriptor(unittest.TestCase): """ Test case for TripDescriptor @@ -28,11 +29,11 @@ def create_instance(): Create instance of TripDescriptor for testing """ instance = TripDescriptor( - trip_id='cenkcouwatkqismwclkg', - route_id='xcbubnxdvyntxzhyqhlb', - direction_id=int(77), - start_time='zbbranwqfukrgdvtvyou', - start_date='prrfvjylxwrjtlfdpfwt', + trip_id='yyedpaxxdxbgsqkpvxcq', + route_id='rdlfvzpmrfspcdqtmmry', + direction_id=int(47), + start_time='pvsoxocwovdmllpbjmwd', + start_date='bdyjnyxldojzjamfueqn', schedule_relationship=Test_ScheduleRelationship.create_instance() ) return instance @@ -42,7 +43,7 @@ def test_trip_id_property(self): """ Test trip_id property """ - test_value = 'cenkcouwatkqismwclkg' + test_value = 'yyedpaxxdxbgsqkpvxcq' self.instance.trip_id = test_value self.assertEqual(self.instance.trip_id, test_value) @@ -50,7 +51,7 @@ def test_route_id_property(self): """ Test route_id property """ - test_value = 'xcbubnxdvyntxzhyqhlb' + test_value = 'rdlfvzpmrfspcdqtmmry' self.instance.route_id = test_value self.assertEqual(self.instance.route_id, test_value) @@ -58,7 +59,7 @@ def test_direction_id_property(self): """ Test direction_id property """ - test_value = int(77) + test_value = int(47) self.instance.direction_id = test_value self.assertEqual(self.instance.direction_id, test_value) @@ -66,7 +67,7 @@ def test_start_time_property(self): """ Test start_time property """ - test_value = 'zbbranwqfukrgdvtvyou' + test_value = 'pvsoxocwovdmllpbjmwd' self.instance.start_time = test_value self.assertEqual(self.instance.start_time, test_value) @@ -74,7 +75,7 @@ def test_start_date_property(self): """ Test start_date property """ - test_value = 'prrfvjylxwrjtlfdpfwt' + test_value = 'bdyjnyxldojzjamfueqn' self.instance.start_date = test_value self.assertEqual(self.instance.start_date, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor.py index b9d1885..4ef5a3b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicledescriptor import VehicleDescriptor + class Test_VehicleDescriptor(unittest.TestCase): """ Test case for VehicleDescriptor @@ -27,9 +28,9 @@ def create_instance(): Create instance of VehicleDescriptor for testing """ instance = VehicleDescriptor( - id='iepxwyvqnkyagvgagrhl', - label='mlfgvmpwzwmrmkrmevar', - license_plate='rxuhtlotyhzueyknaozu' + id='okddyrunbnxkqcjujinc', + label='txtxsibzfhyymiidejdh', + license_plate='gqnzjpqppqmexsslbydp' ) return instance @@ -38,7 +39,7 @@ def test_id_property(self): """ Test id property """ - test_value = 'iepxwyvqnkyagvgagrhl' + test_value = 'okddyrunbnxkqcjujinc' self.instance.id = test_value self.assertEqual(self.instance.id, test_value) @@ -46,7 +47,7 @@ def test_label_property(self): """ Test label property """ - test_value = 'mlfgvmpwzwmrmkrmevar' + test_value = 'txtxsibzfhyymiidejdh' self.instance.label = test_value self.assertEqual(self.instance.label, test_value) @@ -54,7 +55,7 @@ def test_license_plate_property(self): """ Test license_plate property """ - test_value = 'rxuhtlotyhzueyknaozu' + test_value = 'gqnzjpqppqmexsslbydp' self.instance.license_plate = test_value self.assertEqual(self.instance.license_plate, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition.py index c2df03d..5dc27b9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition.py @@ -10,12 +10,13 @@ from gtfs_rt_producer_data.generaltransitfeedrealtime.vehicle.vehicleposition import VehiclePosition from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition_types_congestionlevel import Test_CongestionLevel +from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor import Test_VehicleDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_tripdescriptor import Test_TripDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition_types_occupancystatus import Test_OccupancyStatus from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicleposition_types_vehiclestopstatus import Test_VehicleStopStatus -from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_vehicledescriptor import Test_VehicleDescriptor from test_gtfs_rt_producer_data_generaltransitfeedrealtime_vehicle_position import Test_Position + class Test_VehiclePosition(unittest.TestCase): """ Test case for VehiclePosition @@ -36,10 +37,10 @@ def create_instance(): trip=Test_TripDescriptor.create_instance(), vehicle=Test_VehicleDescriptor.create_instance(), position=Test_Position.create_instance(), - current_stop_sequence=int(90), - stop_id='ghejprvirjtuascktchr', + current_stop_sequence=int(30), + stop_id='fjtujquvgklgvrbqcbvs', current_status=Test_VehicleStopStatus.create_instance(), - timestamp=int(71), + timestamp=int(11), congestion_level=Test_CongestionLevel.create_instance(), occupancy_status=Test_OccupancyStatus.create_instance() ) @@ -74,7 +75,7 @@ def test_current_stop_sequence_property(self): """ Test current_stop_sequence property """ - test_value = int(90) + test_value = int(30) self.instance.current_stop_sequence = test_value self.assertEqual(self.instance.current_stop_sequence, test_value) @@ -82,7 +83,7 @@ def test_stop_id_property(self): """ Test stop_id property """ - test_value = 'ghejprvirjtuascktchr' + test_value = 'fjtujquvgklgvrbqcbvs' self.instance.stop_id = test_value self.assertEqual(self.instance.stop_id, test_value) @@ -98,7 +99,7 @@ def test_timestamp_property(self): """ Test timestamp property """ - test_value = int(71) + test_value = int(11) self.instance.timestamp = test_value self.assertEqual(self.instance.timestamp, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_agency.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_agency.py index ec38db9..9c19d83 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_agency.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_agency.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.agency import Agency + class Test_Agency(unittest.TestCase): """ Test case for Agency @@ -27,14 +28,14 @@ def create_instance(): Create instance of Agency for testing """ instance = Agency( - agencyId='exlkzimboltqsqydmlvy', - agencyName='rvffzmgzqxodrdtzhpsl', - agencyUrl='cpjnlztgmxqrybozbxqn', - agencyTimezone='mxeqmtkttoqrpaisxtiu', - agencyLang='msyhoinufaehtomkvfqt', - agencyPhone='plmvifljzvphtcftmrvu', - agencyFareUrl='atnqnmbycyifvkzqlivd', - agencyEmail='iydsmvsjtzggjqrifrvc' + agencyId='wtyymahbtvjhtywoiqbw', + agencyName='wlywtzyytvvfvjiafusy', + agencyUrl='ngfeeryjjupnkdhnjnyw', + agencyTimezone='rdyfaiodkqhpqrbolkhe', + agencyLang='jgwuxbnecqdujuvhphph', + agencyPhone='baknryrubytimhqnnmyl', + agencyFareUrl='embelkfvpuzwuvhkpbxv', + agencyEmail='ajxslnhqhrqqknhccbcq' ) return instance @@ -43,7 +44,7 @@ def test_agencyId_property(self): """ Test agencyId property """ - test_value = 'exlkzimboltqsqydmlvy' + test_value = 'wtyymahbtvjhtywoiqbw' self.instance.agencyId = test_value self.assertEqual(self.instance.agencyId, test_value) @@ -51,7 +52,7 @@ def test_agencyName_property(self): """ Test agencyName property """ - test_value = 'rvffzmgzqxodrdtzhpsl' + test_value = 'wlywtzyytvvfvjiafusy' self.instance.agencyName = test_value self.assertEqual(self.instance.agencyName, test_value) @@ -59,7 +60,7 @@ def test_agencyUrl_property(self): """ Test agencyUrl property """ - test_value = 'cpjnlztgmxqrybozbxqn' + test_value = 'ngfeeryjjupnkdhnjnyw' self.instance.agencyUrl = test_value self.assertEqual(self.instance.agencyUrl, test_value) @@ -67,7 +68,7 @@ def test_agencyTimezone_property(self): """ Test agencyTimezone property """ - test_value = 'mxeqmtkttoqrpaisxtiu' + test_value = 'rdyfaiodkqhpqrbolkhe' self.instance.agencyTimezone = test_value self.assertEqual(self.instance.agencyTimezone, test_value) @@ -75,7 +76,7 @@ def test_agencyLang_property(self): """ Test agencyLang property """ - test_value = 'msyhoinufaehtomkvfqt' + test_value = 'jgwuxbnecqdujuvhphph' self.instance.agencyLang = test_value self.assertEqual(self.instance.agencyLang, test_value) @@ -83,7 +84,7 @@ def test_agencyPhone_property(self): """ Test agencyPhone property """ - test_value = 'plmvifljzvphtcftmrvu' + test_value = 'baknryrubytimhqnnmyl' self.instance.agencyPhone = test_value self.assertEqual(self.instance.agencyPhone, test_value) @@ -91,7 +92,7 @@ def test_agencyFareUrl_property(self): """ Test agencyFareUrl property """ - test_value = 'atnqnmbycyifvkzqlivd' + test_value = 'embelkfvpuzwuvhkpbxv' self.instance.agencyFareUrl = test_value self.assertEqual(self.instance.agencyFareUrl, test_value) @@ -99,7 +100,7 @@ def test_agencyEmail_property(self): """ Test agencyEmail property """ - test_value = 'iydsmvsjtzggjqrifrvc' + test_value = 'ajxslnhqhrqqknhccbcq' self.instance.agencyEmail = test_value self.assertEqual(self.instance.agencyEmail, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_areas.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_areas.py index b87cde8..1e15d44 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_areas.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_areas.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.areas import Areas + class Test_Areas(unittest.TestCase): """ Test case for Areas @@ -27,10 +28,10 @@ def create_instance(): Create instance of Areas for testing """ instance = Areas( - areaId='vyjdvufplupeyguygkqr', - areaName='fqcppadxpulxkukvwark', - areaDesc='tdncnceliydnpajvhffo', - areaUrl='nsulfjbpbdahhneiucqh' + areaId='nvurooowwymloithehrg', + areaName='kfnkbhcowrazdtpkgldo', + areaDesc='jolqlthepdnfuidtfaee', + areaUrl='eatgptubkpcgscefipaf' ) return instance @@ -39,7 +40,7 @@ def test_areaId_property(self): """ Test areaId property """ - test_value = 'vyjdvufplupeyguygkqr' + test_value = 'nvurooowwymloithehrg' self.instance.areaId = test_value self.assertEqual(self.instance.areaId, test_value) @@ -47,7 +48,7 @@ def test_areaName_property(self): """ Test areaName property """ - test_value = 'fqcppadxpulxkukvwark' + test_value = 'kfnkbhcowrazdtpkgldo' self.instance.areaName = test_value self.assertEqual(self.instance.areaName, test_value) @@ -55,7 +56,7 @@ def test_areaDesc_property(self): """ Test areaDesc property """ - test_value = 'tdncnceliydnpajvhffo' + test_value = 'jolqlthepdnfuidtfaee' self.instance.areaDesc = test_value self.assertEqual(self.instance.areaDesc, test_value) @@ -63,7 +64,7 @@ def test_areaUrl_property(self): """ Test areaUrl property """ - test_value = 'nsulfjbpbdahhneiucqh' + test_value = 'eatgptubkpcgscefipaf' self.instance.areaUrl = test_value self.assertEqual(self.instance.areaUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_attributions.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_attributions.py index ec6e73b..278bb13 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_attributions.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_attributions.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.attributions import Attributions + class Test_Attributions(unittest.TestCase): """ Test case for Attributions @@ -27,17 +28,17 @@ def create_instance(): Create instance of Attributions for testing """ instance = Attributions( - attributionId='adhcpfqtmffgnegtkrfq', - agencyId='tixvweuaacblcydkcpss', - routeId='qnnyynrpkuhvcoqmqqmp', - tripId='pgmecixzbjsncnvanqwf', - organizationName='vafalxnzkzlwavmalngt', - isProducer=int(32), - isOperator=int(40), - isAuthority=int(26), - attributionUrl='twushktonkmvlorzsljm', - attributionEmail='myjxwsrbieqgxhqpbgee', - attributionPhone='htejliwekbcximstadon' + attributionId='bwptbceykmeixyluciui', + agencyId='obqqopoqsmutelnzkvgm', + routeId='olqziqolzsvgurmawyed', + tripId='fdxieozjszvvzwicznrt', + organizationName='ddvphbfacmlprxzhjyto', + isProducer=int(53), + isOperator=int(88), + isAuthority=int(81), + attributionUrl='vrqssplljvouxhqvhyni', + attributionEmail='tfninppmkhstvmumctxo', + attributionPhone='sxohfhcgsnrjjczyhjrx' ) return instance @@ -46,7 +47,7 @@ def test_attributionId_property(self): """ Test attributionId property """ - test_value = 'adhcpfqtmffgnegtkrfq' + test_value = 'bwptbceykmeixyluciui' self.instance.attributionId = test_value self.assertEqual(self.instance.attributionId, test_value) @@ -54,7 +55,7 @@ def test_agencyId_property(self): """ Test agencyId property """ - test_value = 'tixvweuaacblcydkcpss' + test_value = 'obqqopoqsmutelnzkvgm' self.instance.agencyId = test_value self.assertEqual(self.instance.agencyId, test_value) @@ -62,7 +63,7 @@ def test_routeId_property(self): """ Test routeId property """ - test_value = 'qnnyynrpkuhvcoqmqqmp' + test_value = 'olqziqolzsvgurmawyed' self.instance.routeId = test_value self.assertEqual(self.instance.routeId, test_value) @@ -70,7 +71,7 @@ def test_tripId_property(self): """ Test tripId property """ - test_value = 'pgmecixzbjsncnvanqwf' + test_value = 'fdxieozjszvvzwicznrt' self.instance.tripId = test_value self.assertEqual(self.instance.tripId, test_value) @@ -78,7 +79,7 @@ def test_organizationName_property(self): """ Test organizationName property """ - test_value = 'vafalxnzkzlwavmalngt' + test_value = 'ddvphbfacmlprxzhjyto' self.instance.organizationName = test_value self.assertEqual(self.instance.organizationName, test_value) @@ -86,7 +87,7 @@ def test_isProducer_property(self): """ Test isProducer property """ - test_value = int(32) + test_value = int(53) self.instance.isProducer = test_value self.assertEqual(self.instance.isProducer, test_value) @@ -94,7 +95,7 @@ def test_isOperator_property(self): """ Test isOperator property """ - test_value = int(40) + test_value = int(88) self.instance.isOperator = test_value self.assertEqual(self.instance.isOperator, test_value) @@ -102,7 +103,7 @@ def test_isAuthority_property(self): """ Test isAuthority property """ - test_value = int(26) + test_value = int(81) self.instance.isAuthority = test_value self.assertEqual(self.instance.isAuthority, test_value) @@ -110,7 +111,7 @@ def test_attributionUrl_property(self): """ Test attributionUrl property """ - test_value = 'twushktonkmvlorzsljm' + test_value = 'vrqssplljvouxhqvhyni' self.instance.attributionUrl = test_value self.assertEqual(self.instance.attributionUrl, test_value) @@ -118,7 +119,7 @@ def test_attributionEmail_property(self): """ Test attributionEmail property """ - test_value = 'myjxwsrbieqgxhqpbgee' + test_value = 'tfninppmkhstvmumctxo' self.instance.attributionEmail = test_value self.assertEqual(self.instance.attributionEmail, test_value) @@ -126,7 +127,7 @@ def test_attributionPhone_property(self): """ Test attributionPhone property """ - test_value = 'htejliwekbcximstadon' + test_value = 'sxohfhcgsnrjjczyhjrx' self.instance.attributionPhone = test_value self.assertEqual(self.instance.attributionPhone, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_bookingrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_bookingrules.py index d602007..89ea23c 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_bookingrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_bookingrules.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.bookingrules import BookingRules + class Test_BookingRules(unittest.TestCase): """ Test case for BookingRules @@ -27,10 +28,10 @@ def create_instance(): Create instance of BookingRules for testing """ instance = BookingRules( - bookingRuleId='voaymqakzvuiyeydoneb', - bookingRuleName='ytmnvmzmruyvzlsyezia', - bookingRuleDesc='fhvqosoxywtxphunncys', - bookingRuleUrl='swxcvgjdsdxkrdumktbj' + bookingRuleId='cweemwipqlfcdndyrhtm', + bookingRuleName='lgstdiptegarzvlaibtr', + bookingRuleDesc='ndnhusmbnhsfwyjtlutr', + bookingRuleUrl='noivxplxphhffkswhrsu' ) return instance @@ -39,7 +40,7 @@ def test_bookingRuleId_property(self): """ Test bookingRuleId property """ - test_value = 'voaymqakzvuiyeydoneb' + test_value = 'cweemwipqlfcdndyrhtm' self.instance.bookingRuleId = test_value self.assertEqual(self.instance.bookingRuleId, test_value) @@ -47,7 +48,7 @@ def test_bookingRuleName_property(self): """ Test bookingRuleName property """ - test_value = 'ytmnvmzmruyvzlsyezia' + test_value = 'lgstdiptegarzvlaibtr' self.instance.bookingRuleName = test_value self.assertEqual(self.instance.bookingRuleName, test_value) @@ -55,7 +56,7 @@ def test_bookingRuleDesc_property(self): """ Test bookingRuleDesc property """ - test_value = 'fhvqosoxywtxphunncys' + test_value = 'ndnhusmbnhsfwyjtlutr' self.instance.bookingRuleDesc = test_value self.assertEqual(self.instance.bookingRuleDesc, test_value) @@ -63,7 +64,7 @@ def test_bookingRuleUrl_property(self): """ Test bookingRuleUrl property """ - test_value = 'swxcvgjdsdxkrdumktbj' + test_value = 'noivxplxphhffkswhrsu' self.instance.bookingRuleUrl = test_value self.assertEqual(self.instance.bookingRuleUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar.py index f1c3958..e15d533 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.calendar import Calendar from test_gtfs_rt_producer_data_generaltransitfeedstatic_serviceavailability import Test_ServiceAvailability + class Test_Calendar(unittest.TestCase): """ Test case for Calendar @@ -28,7 +29,7 @@ def create_instance(): Create instance of Calendar for testing """ instance = Calendar( - serviceId='czyphiynzkpwlrdsgldm', + serviceId='rqflmkgyhljkdwmhwdsh', monday=Test_ServiceAvailability.create_instance(), tuesday=Test_ServiceAvailability.create_instance(), wednesday=Test_ServiceAvailability.create_instance(), @@ -36,8 +37,8 @@ def create_instance(): friday=Test_ServiceAvailability.create_instance(), saturday=Test_ServiceAvailability.create_instance(), sunday=Test_ServiceAvailability.create_instance(), - startDate='pwtkdkuiofwefjjejwcc', - endDate='wzuxxvltzzmtbfjqmeaf' + startDate='xxrjdcicjstmanvblymi', + endDate='fnyyuphjxgnburumytxm' ) return instance @@ -46,7 +47,7 @@ def test_serviceId_property(self): """ Test serviceId property """ - test_value = 'czyphiynzkpwlrdsgldm' + test_value = 'rqflmkgyhljkdwmhwdsh' self.instance.serviceId = test_value self.assertEqual(self.instance.serviceId, test_value) @@ -110,7 +111,7 @@ def test_startDate_property(self): """ Test startDate property """ - test_value = 'pwtkdkuiofwefjjejwcc' + test_value = 'xxrjdcicjstmanvblymi' self.instance.startDate = test_value self.assertEqual(self.instance.startDate, test_value) @@ -118,7 +119,7 @@ def test_endDate_property(self): """ Test endDate property """ - test_value = 'wzuxxvltzzmtbfjqmeaf' + test_value = 'fnyyuphjxgnburumytxm' self.instance.endDate = test_value self.assertEqual(self.instance.endDate, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates.py index f2b7d3c..417ace9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates.py @@ -11,6 +11,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.calendardates import CalendarDates from test_gtfs_rt_producer_data_generaltransitfeedstatic_exceptiontype import Test_ExceptionType + class Test_CalendarDates(unittest.TestCase): """ Test case for CalendarDates @@ -28,8 +29,8 @@ def create_instance(): Create instance of CalendarDates for testing """ instance = CalendarDates( - serviceId='yvyupissrvwcfabsidcw', - date='esdqlpjgsbnblqmerxuj', + serviceId='bksyabmbnaiyfrzvuftq', + date='hbxpizhzrauiiijoyiww', exceptionType=Test_ExceptionType.create_instance() ) return instance @@ -39,7 +40,7 @@ def test_serviceId_property(self): """ Test serviceId property """ - test_value = 'yvyupissrvwcfabsidcw' + test_value = 'bksyabmbnaiyfrzvuftq' self.instance.serviceId = test_value self.assertEqual(self.instance.serviceId, test_value) @@ -47,7 +48,7 @@ def test_date_property(self): """ Test date property """ - test_value = 'esdqlpjgsbnblqmerxuj' + test_value = 'hbxpizhzrauiiijoyiww' self.instance.date = test_value self.assertEqual(self.instance.date, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareattributes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareattributes.py index 01abbb4..1e64877 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareattributes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareattributes.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.fareattributes import FareAttributes + class Test_FareAttributes(unittest.TestCase): """ Test case for FareAttributes @@ -27,13 +28,13 @@ def create_instance(): Create instance of FareAttributes for testing """ instance = FareAttributes( - fareId='xgnhiscetdjkzvyonscn', - price=float(23.683224915538638), - currencyType='jmogzurmosoorgeuqlbk', - paymentMethod=int(35), - transfers=int(29), - agencyId='nfyiccnhvrzwqpvvszgz', - transferDuration=int(26) + fareId='agbmnpiaoysimmubyuqu', + price=float(50.39431017920468), + currencyType='utvflopaurtoicqdcebk', + paymentMethod=int(34), + transfers=int(63), + agencyId='mewwocpcktemydtubprd', + transferDuration=int(46) ) return instance @@ -42,7 +43,7 @@ def test_fareId_property(self): """ Test fareId property """ - test_value = 'xgnhiscetdjkzvyonscn' + test_value = 'agbmnpiaoysimmubyuqu' self.instance.fareId = test_value self.assertEqual(self.instance.fareId, test_value) @@ -50,7 +51,7 @@ def test_price_property(self): """ Test price property """ - test_value = float(23.683224915538638) + test_value = float(50.39431017920468) self.instance.price = test_value self.assertEqual(self.instance.price, test_value) @@ -58,7 +59,7 @@ def test_currencyType_property(self): """ Test currencyType property """ - test_value = 'jmogzurmosoorgeuqlbk' + test_value = 'utvflopaurtoicqdcebk' self.instance.currencyType = test_value self.assertEqual(self.instance.currencyType, test_value) @@ -66,7 +67,7 @@ def test_paymentMethod_property(self): """ Test paymentMethod property """ - test_value = int(35) + test_value = int(34) self.instance.paymentMethod = test_value self.assertEqual(self.instance.paymentMethod, test_value) @@ -74,7 +75,7 @@ def test_transfers_property(self): """ Test transfers property """ - test_value = int(29) + test_value = int(63) self.instance.transfers = test_value self.assertEqual(self.instance.transfers, test_value) @@ -82,7 +83,7 @@ def test_agencyId_property(self): """ Test agencyId property """ - test_value = 'nfyiccnhvrzwqpvvszgz' + test_value = 'mewwocpcktemydtubprd' self.instance.agencyId = test_value self.assertEqual(self.instance.agencyId, test_value) @@ -90,7 +91,7 @@ def test_transferDuration_property(self): """ Test transferDuration property """ - test_value = int(26) + test_value = int(46) self.instance.transferDuration = test_value self.assertEqual(self.instance.transferDuration, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farelegrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farelegrules.py index b74c368..1480db7 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farelegrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farelegrules.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.farelegrules import FareLegRules + class Test_FareLegRules(unittest.TestCase): """ Test case for FareLegRules @@ -27,12 +28,12 @@ def create_instance(): Create instance of FareLegRules for testing """ instance = FareLegRules( - fareLegRuleId='ovfbibcihfzqcckxeemc', - fareProductId='smzefxmjdwlbgjtuvzga', - legGroupId='andtgdcrphfkqxwnxsfx', - networkId='zsomgvdfvjfxvxbnqvuc', - fromAreaId='euaxgnnmrgomzgsddrwv', - toAreaId='sevthhgbalqfxqxyzrjo' + fareLegRuleId='tyuboylsydzpahjvsqnc', + fareProductId='fyiroseqagkmghwsktma', + legGroupId='nknrbfvcrngkqsbooeyo', + networkId='zwgvvuccchpswozxbcam', + fromAreaId='yoeqbljuliczxsybcehx', + toAreaId='eondmrfxuntgelbbgrsw' ) return instance @@ -41,7 +42,7 @@ def test_fareLegRuleId_property(self): """ Test fareLegRuleId property """ - test_value = 'ovfbibcihfzqcckxeemc' + test_value = 'tyuboylsydzpahjvsqnc' self.instance.fareLegRuleId = test_value self.assertEqual(self.instance.fareLegRuleId, test_value) @@ -49,7 +50,7 @@ def test_fareProductId_property(self): """ Test fareProductId property """ - test_value = 'smzefxmjdwlbgjtuvzga' + test_value = 'fyiroseqagkmghwsktma' self.instance.fareProductId = test_value self.assertEqual(self.instance.fareProductId, test_value) @@ -57,7 +58,7 @@ def test_legGroupId_property(self): """ Test legGroupId property """ - test_value = 'andtgdcrphfkqxwnxsfx' + test_value = 'nknrbfvcrngkqsbooeyo' self.instance.legGroupId = test_value self.assertEqual(self.instance.legGroupId, test_value) @@ -65,7 +66,7 @@ def test_networkId_property(self): """ Test networkId property """ - test_value = 'zsomgvdfvjfxvxbnqvuc' + test_value = 'zwgvvuccchpswozxbcam' self.instance.networkId = test_value self.assertEqual(self.instance.networkId, test_value) @@ -73,7 +74,7 @@ def test_fromAreaId_property(self): """ Test fromAreaId property """ - test_value = 'euaxgnnmrgomzgsddrwv' + test_value = 'yoeqbljuliczxsybcehx' self.instance.fromAreaId = test_value self.assertEqual(self.instance.fromAreaId, test_value) @@ -81,7 +82,7 @@ def test_toAreaId_property(self): """ Test toAreaId property """ - test_value = 'sevthhgbalqfxqxyzrjo' + test_value = 'eondmrfxuntgelbbgrsw' self.instance.toAreaId = test_value self.assertEqual(self.instance.toAreaId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faremedia.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faremedia.py index 1262785..df6f2d6 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faremedia.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faremedia.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.faremedia import FareMedia + class Test_FareMedia(unittest.TestCase): """ Test case for FareMedia @@ -27,10 +28,10 @@ def create_instance(): Create instance of FareMedia for testing """ instance = FareMedia( - fareMediaId='egxxeuuvicnngiitlzbr', - fareMediaName='mbgcwbqqiwbboxkxtmxd', - fareMediaDesc='khykphimfpnzvnqnhgwf', - fareMediaUrl='bvmjmcqyjouethyhfbgt' + fareMediaId='dekytnmsbpqmxuimyych', + fareMediaName='lijvioehsnjilyrytpmn', + fareMediaDesc='pbuztiqdeoorpkkagwhv', + fareMediaUrl='gztgagyhfpbnagoramyn' ) return instance @@ -39,7 +40,7 @@ def test_fareMediaId_property(self): """ Test fareMediaId property """ - test_value = 'egxxeuuvicnngiitlzbr' + test_value = 'dekytnmsbpqmxuimyych' self.instance.fareMediaId = test_value self.assertEqual(self.instance.fareMediaId, test_value) @@ -47,7 +48,7 @@ def test_fareMediaName_property(self): """ Test fareMediaName property """ - test_value = 'mbgcwbqqiwbboxkxtmxd' + test_value = 'lijvioehsnjilyrytpmn' self.instance.fareMediaName = test_value self.assertEqual(self.instance.fareMediaName, test_value) @@ -55,7 +56,7 @@ def test_fareMediaDesc_property(self): """ Test fareMediaDesc property """ - test_value = 'khykphimfpnzvnqnhgwf' + test_value = 'pbuztiqdeoorpkkagwhv' self.instance.fareMediaDesc = test_value self.assertEqual(self.instance.fareMediaDesc, test_value) @@ -63,7 +64,7 @@ def test_fareMediaUrl_property(self): """ Test fareMediaUrl property """ - test_value = 'bvmjmcqyjouethyhfbgt' + test_value = 'gztgagyhfpbnagoramyn' self.instance.fareMediaUrl = test_value self.assertEqual(self.instance.fareMediaUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareproducts.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareproducts.py index d5bd2d7..3860544 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareproducts.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_fareproducts.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.fareproducts import FareProducts + class Test_FareProducts(unittest.TestCase): """ Test case for FareProducts @@ -27,10 +28,10 @@ def create_instance(): Create instance of FareProducts for testing """ instance = FareProducts( - fareProductId='oprpyrrjregyzzjaeoec', - fareProductName='julwywixcyiymxxanbut', - fareProductDesc='kedhverjwpqxtcmtggpa', - fareProductUrl='xtunmzodhyeghaxfrlma' + fareProductId='nqaxnelvwngnwrdppzdf', + fareProductName='wczckotrsjsfkkfwprrj', + fareProductDesc='xoafhfsimofdturgmwst', + fareProductUrl='nvjpmwtaipfniifeiros' ) return instance @@ -39,7 +40,7 @@ def test_fareProductId_property(self): """ Test fareProductId property """ - test_value = 'oprpyrrjregyzzjaeoec' + test_value = 'nqaxnelvwngnwrdppzdf' self.instance.fareProductId = test_value self.assertEqual(self.instance.fareProductId, test_value) @@ -47,7 +48,7 @@ def test_fareProductName_property(self): """ Test fareProductName property """ - test_value = 'julwywixcyiymxxanbut' + test_value = 'wczckotrsjsfkkfwprrj' self.instance.fareProductName = test_value self.assertEqual(self.instance.fareProductName, test_value) @@ -55,7 +56,7 @@ def test_fareProductDesc_property(self): """ Test fareProductDesc property """ - test_value = 'kedhverjwpqxtcmtggpa' + test_value = 'xoafhfsimofdturgmwst' self.instance.fareProductDesc = test_value self.assertEqual(self.instance.fareProductDesc, test_value) @@ -63,7 +64,7 @@ def test_fareProductUrl_property(self): """ Test fareProductUrl property """ - test_value = 'xtunmzodhyeghaxfrlma' + test_value = 'nvjpmwtaipfniifeiros' self.instance.fareProductUrl = test_value self.assertEqual(self.instance.fareProductUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farerules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farerules.py index 265b8c7..b176b90 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farerules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_farerules.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.farerules import FareRules + class Test_FareRules(unittest.TestCase): """ Test case for FareRules @@ -27,11 +28,11 @@ def create_instance(): Create instance of FareRules for testing """ instance = FareRules( - fareId='ttkrfcngztnpkxukaemh', - routeId='bpowcvruzanlviqweohl', - originId='qodupbavlffdtmkoytjr', - destinationId='semjqkpjulfpqzqmxxwh', - containsId='svlgjcyssrxkejenxdaz' + fareId='ttnqkqtjxbwsdobtskrl', + routeId='wulhsirwheytcyfufogc', + originId='leycyycmxousiycleakd', + destinationId='fqfhyeaimpugrgedfvbf', + containsId='ariogpzbaycafgiqojcw' ) return instance @@ -40,7 +41,7 @@ def test_fareId_property(self): """ Test fareId property """ - test_value = 'ttkrfcngztnpkxukaemh' + test_value = 'ttnqkqtjxbwsdobtskrl' self.instance.fareId = test_value self.assertEqual(self.instance.fareId, test_value) @@ -48,7 +49,7 @@ def test_routeId_property(self): """ Test routeId property """ - test_value = 'bpowcvruzanlviqweohl' + test_value = 'wulhsirwheytcyfufogc' self.instance.routeId = test_value self.assertEqual(self.instance.routeId, test_value) @@ -56,7 +57,7 @@ def test_originId_property(self): """ Test originId property """ - test_value = 'qodupbavlffdtmkoytjr' + test_value = 'leycyycmxousiycleakd' self.instance.originId = test_value self.assertEqual(self.instance.originId, test_value) @@ -64,7 +65,7 @@ def test_destinationId_property(self): """ Test destinationId property """ - test_value = 'semjqkpjulfpqzqmxxwh' + test_value = 'fqfhyeaimpugrgedfvbf' self.instance.destinationId = test_value self.assertEqual(self.instance.destinationId, test_value) @@ -72,7 +73,7 @@ def test_containsId_property(self): """ Test containsId property """ - test_value = 'svlgjcyssrxkejenxdaz' + test_value = 'ariogpzbaycafgiqojcw' self.instance.containsId = test_value self.assertEqual(self.instance.containsId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faretransferrules.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faretransferrules.py index ecab834..b7d6674 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faretransferrules.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_faretransferrules.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.faretransferrules import FareTransferRules + class Test_FareTransferRules(unittest.TestCase): """ Test case for FareTransferRules @@ -27,13 +28,13 @@ def create_instance(): Create instance of FareTransferRules for testing """ instance = FareTransferRules( - fareTransferRuleId='govgpqebhiylvomaunjq', - fareProductId='sxtgrvwhqcwytqkuvpmm', - transferCount=int(62), - fromLegGroupId='eogrgfgfjcwxirtdlmyz', - toLegGroupId='enolxksgcoeiioyiqwvo', - duration=int(50), - durationType='jjqndfqaqxyxqchkvunb' + fareTransferRuleId='exmmzijkpsafmgxplfov', + fareProductId='vkhweszmbzvntgdmhfqe', + transferCount=int(77), + fromLegGroupId='pbqnpembpbrsluswaenn', + toLegGroupId='pmykpgzlpttstciiyebc', + duration=int(6), + durationType='cmkkhwzkrcdkfiguehht' ) return instance @@ -42,7 +43,7 @@ def test_fareTransferRuleId_property(self): """ Test fareTransferRuleId property """ - test_value = 'govgpqebhiylvomaunjq' + test_value = 'exmmzijkpsafmgxplfov' self.instance.fareTransferRuleId = test_value self.assertEqual(self.instance.fareTransferRuleId, test_value) @@ -50,7 +51,7 @@ def test_fareProductId_property(self): """ Test fareProductId property """ - test_value = 'sxtgrvwhqcwytqkuvpmm' + test_value = 'vkhweszmbzvntgdmhfqe' self.instance.fareProductId = test_value self.assertEqual(self.instance.fareProductId, test_value) @@ -58,7 +59,7 @@ def test_transferCount_property(self): """ Test transferCount property """ - test_value = int(62) + test_value = int(77) self.instance.transferCount = test_value self.assertEqual(self.instance.transferCount, test_value) @@ -66,7 +67,7 @@ def test_fromLegGroupId_property(self): """ Test fromLegGroupId property """ - test_value = 'eogrgfgfjcwxirtdlmyz' + test_value = 'pbqnpembpbrsluswaenn' self.instance.fromLegGroupId = test_value self.assertEqual(self.instance.fromLegGroupId, test_value) @@ -74,7 +75,7 @@ def test_toLegGroupId_property(self): """ Test toLegGroupId property """ - test_value = 'enolxksgcoeiioyiqwvo' + test_value = 'pmykpgzlpttstciiyebc' self.instance.toLegGroupId = test_value self.assertEqual(self.instance.toLegGroupId, test_value) @@ -82,7 +83,7 @@ def test_duration_property(self): """ Test duration property """ - test_value = int(50) + test_value = int(6) self.instance.duration = test_value self.assertEqual(self.instance.duration, test_value) @@ -90,7 +91,7 @@ def test_durationType_property(self): """ Test durationType property """ - test_value = 'jjqndfqaqxyxqchkvunb' + test_value = 'cmkkhwzkrcdkfiguehht' self.instance.durationType = test_value self.assertEqual(self.instance.durationType, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_feedinfo.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_feedinfo.py index a42a1d4..55aba7a 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_feedinfo.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_feedinfo.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.feedinfo import FeedInfo + class Test_FeedInfo(unittest.TestCase): """ Test case for FeedInfo @@ -27,15 +28,15 @@ def create_instance(): Create instance of FeedInfo for testing """ instance = FeedInfo( - feedPublisherName='rgmpzecaqjtfoxcxnxxg', - feedPublisherUrl='mzzwhabkkvxbocwkickx', - feedLang='vsepzxlmktvdbetgekvh', - defaultLang='etwmytxjvkpfgxqpotpq', - feedStartDate='luwljtamyyptkqydgdsg', - feedEndDate='enphujpyyqszgtjyiipl', - feedVersion='dlyrjbursyhapiycwzps', - feedContactEmail='hmnrqbclbvzodpblnzbe', - feedContactUrl='ztjyhmnupgcrnkprtkkg' + feedPublisherName='idfpqzinuppjmyfkivks', + feedPublisherUrl='wvhrqycyhfwasikjxvrk', + feedLang='zuzglwchokaashigmsbl', + defaultLang='jztfwdwuqnhnmgaxyahs', + feedStartDate='cyhkdfbvnpqrefnxzkym', + feedEndDate='fqfamvdjrnxjkpxzegcb', + feedVersion='nptxmhhqqxnipizfuuhz', + feedContactEmail='yferfhyrftuubefaebbq', + feedContactUrl='aolzmqzcuptaartrdkrh' ) return instance @@ -44,7 +45,7 @@ def test_feedPublisherName_property(self): """ Test feedPublisherName property """ - test_value = 'rgmpzecaqjtfoxcxnxxg' + test_value = 'idfpqzinuppjmyfkivks' self.instance.feedPublisherName = test_value self.assertEqual(self.instance.feedPublisherName, test_value) @@ -52,7 +53,7 @@ def test_feedPublisherUrl_property(self): """ Test feedPublisherUrl property """ - test_value = 'mzzwhabkkvxbocwkickx' + test_value = 'wvhrqycyhfwasikjxvrk' self.instance.feedPublisherUrl = test_value self.assertEqual(self.instance.feedPublisherUrl, test_value) @@ -60,7 +61,7 @@ def test_feedLang_property(self): """ Test feedLang property """ - test_value = 'vsepzxlmktvdbetgekvh' + test_value = 'zuzglwchokaashigmsbl' self.instance.feedLang = test_value self.assertEqual(self.instance.feedLang, test_value) @@ -68,7 +69,7 @@ def test_defaultLang_property(self): """ Test defaultLang property """ - test_value = 'etwmytxjvkpfgxqpotpq' + test_value = 'jztfwdwuqnhnmgaxyahs' self.instance.defaultLang = test_value self.assertEqual(self.instance.defaultLang, test_value) @@ -76,7 +77,7 @@ def test_feedStartDate_property(self): """ Test feedStartDate property """ - test_value = 'luwljtamyyptkqydgdsg' + test_value = 'cyhkdfbvnpqrefnxzkym' self.instance.feedStartDate = test_value self.assertEqual(self.instance.feedStartDate, test_value) @@ -84,7 +85,7 @@ def test_feedEndDate_property(self): """ Test feedEndDate property """ - test_value = 'enphujpyyqszgtjyiipl' + test_value = 'fqfamvdjrnxjkpxzegcb' self.instance.feedEndDate = test_value self.assertEqual(self.instance.feedEndDate, test_value) @@ -92,7 +93,7 @@ def test_feedVersion_property(self): """ Test feedVersion property """ - test_value = 'dlyrjbursyhapiycwzps' + test_value = 'nptxmhhqqxnipizfuuhz' self.instance.feedVersion = test_value self.assertEqual(self.instance.feedVersion, test_value) @@ -100,7 +101,7 @@ def test_feedContactEmail_property(self): """ Test feedContactEmail property """ - test_value = 'hmnrqbclbvzodpblnzbe' + test_value = 'yferfhyrftuubefaebbq' self.instance.feedContactEmail = test_value self.assertEqual(self.instance.feedContactEmail, test_value) @@ -108,7 +109,7 @@ def test_feedContactUrl_property(self): """ Test feedContactUrl property """ - test_value = 'ztjyhmnupgcrnkprtkkg' + test_value = 'aolzmqzcuptaartrdkrh' self.instance.feedContactUrl = test_value self.assertEqual(self.instance.feedContactUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_frequencies.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_frequencies.py index 8702b5a..1bd73a7 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_frequencies.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_frequencies.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.frequencies import Frequencies + class Test_Frequencies(unittest.TestCase): """ Test case for Frequencies @@ -27,11 +28,11 @@ def create_instance(): Create instance of Frequencies for testing """ instance = Frequencies( - tripId='gjwwztawlakcvtocfeuj', - startTime='qhtgrdwnmgalkeukpnmb', - endTime='kdznwysjddwjmqalgach', - headwaySecs=int(86), - exactTimes=int(49) + tripId='fjxtdzfttriezvoqfmew', + startTime='mmzcybolqguwsxjhuley', + endTime='pfumxgixdnkereykdcye', + headwaySecs=int(1), + exactTimes=int(35) ) return instance @@ -40,7 +41,7 @@ def test_tripId_property(self): """ Test tripId property """ - test_value = 'gjwwztawlakcvtocfeuj' + test_value = 'fjxtdzfttriezvoqfmew' self.instance.tripId = test_value self.assertEqual(self.instance.tripId, test_value) @@ -48,7 +49,7 @@ def test_startTime_property(self): """ Test startTime property """ - test_value = 'qhtgrdwnmgalkeukpnmb' + test_value = 'mmzcybolqguwsxjhuley' self.instance.startTime = test_value self.assertEqual(self.instance.startTime, test_value) @@ -56,7 +57,7 @@ def test_endTime_property(self): """ Test endTime property """ - test_value = 'kdznwysjddwjmqalgach' + test_value = 'pfumxgixdnkereykdcye' self.instance.endTime = test_value self.assertEqual(self.instance.endTime, test_value) @@ -64,7 +65,7 @@ def test_headwaySecs_property(self): """ Test headwaySecs property """ - test_value = int(86) + test_value = int(1) self.instance.headwaySecs = test_value self.assertEqual(self.instance.headwaySecs, test_value) @@ -72,7 +73,7 @@ def test_exactTimes_property(self): """ Test exactTimes property """ - test_value = int(49) + test_value = int(35) self.instance.exactTimes = test_value self.assertEqual(self.instance.exactTimes, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_levels.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_levels.py index f86b38e..02e2eea 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_levels.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_levels.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.levels import Levels + class Test_Levels(unittest.TestCase): """ Test case for Levels @@ -27,9 +28,9 @@ def create_instance(): Create instance of Levels for testing """ instance = Levels( - levelId='khuikpzjukkqkhugtemu', - levelIndex=float(41.047808343759684), - levelName='aqxmkrdwousvjlcwkqvd' + levelId='adepwwutlzffliyzedzq', + levelIndex=float(32.29515479984838), + levelName='uvajkqgxstpohcdyihli' ) return instance @@ -38,7 +39,7 @@ def test_levelId_property(self): """ Test levelId property """ - test_value = 'khuikpzjukkqkhugtemu' + test_value = 'adepwwutlzffliyzedzq' self.instance.levelId = test_value self.assertEqual(self.instance.levelId, test_value) @@ -46,7 +47,7 @@ def test_levelIndex_property(self): """ Test levelIndex property """ - test_value = float(41.047808343759684) + test_value = float(32.29515479984838) self.instance.levelIndex = test_value self.assertEqual(self.instance.levelIndex, test_value) @@ -54,7 +55,7 @@ def test_levelName_property(self): """ Test levelName property """ - test_value = 'aqxmkrdwousvjlcwkqvd' + test_value = 'uvajkqgxstpohcdyihli' self.instance.levelName = test_value self.assertEqual(self.instance.levelName, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgeojson.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgeojson.py index c11913c..0180be9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgeojson.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgeojson.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.locationgeojson import LocationGeoJson + class Test_LocationGeoJson(unittest.TestCase): """ Test case for LocationGeoJson @@ -27,9 +28,9 @@ def create_instance(): Create instance of LocationGeoJson for testing """ instance = LocationGeoJson( - locationGeoJsonId='pgmgsuvknfusdqwtssys', - locationGeoJsonType='wqajyiaiytfcioyxsbgp', - locationGeoJsonData='uopwefqzjuwqeijyppvj' + locationGeoJsonId='icwpipfnjxctujnacjnl', + locationGeoJsonType='aihywqwwmiujbepezyeo', + locationGeoJsonData='hlkiwmzmeshjdcklbtua' ) return instance @@ -38,7 +39,7 @@ def test_locationGeoJsonId_property(self): """ Test locationGeoJsonId property """ - test_value = 'pgmgsuvknfusdqwtssys' + test_value = 'icwpipfnjxctujnacjnl' self.instance.locationGeoJsonId = test_value self.assertEqual(self.instance.locationGeoJsonId, test_value) @@ -46,7 +47,7 @@ def test_locationGeoJsonType_property(self): """ Test locationGeoJsonType property """ - test_value = 'wqajyiaiytfcioyxsbgp' + test_value = 'aihywqwwmiujbepezyeo' self.instance.locationGeoJsonType = test_value self.assertEqual(self.instance.locationGeoJsonType, test_value) @@ -54,7 +55,7 @@ def test_locationGeoJsonData_property(self): """ Test locationGeoJsonData property """ - test_value = 'uopwefqzjuwqeijyppvj' + test_value = 'hlkiwmzmeshjdcklbtua' self.instance.locationGeoJsonData = test_value self.assertEqual(self.instance.locationGeoJsonData, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroups.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroups.py index ec0f6ae..2120389 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroups.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroups.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.locationgroups import LocationGroups + class Test_LocationGroups(unittest.TestCase): """ Test case for LocationGroups @@ -27,10 +28,10 @@ def create_instance(): Create instance of LocationGroups for testing """ instance = LocationGroups( - locationGroupId='qyxeifbgyeukduqrumdg', - locationGroupName='btnwpvwlrbszisfiuals', - locationGroupDesc='ggwvrbpdguicauubqwcy', - locationGroupUrl='tbupmeyrjhnszlvgxjgu' + locationGroupId='uloebyrrwpxmcjldyhwd', + locationGroupName='dvrnopuzoaczdpncjatn', + locationGroupDesc='cqpqnvsnylvpmghokjfj', + locationGroupUrl='gczugwjrvtentfmhsond' ) return instance @@ -39,7 +40,7 @@ def test_locationGroupId_property(self): """ Test locationGroupId property """ - test_value = 'qyxeifbgyeukduqrumdg' + test_value = 'uloebyrrwpxmcjldyhwd' self.instance.locationGroupId = test_value self.assertEqual(self.instance.locationGroupId, test_value) @@ -47,7 +48,7 @@ def test_locationGroupName_property(self): """ Test locationGroupName property """ - test_value = 'btnwpvwlrbszisfiuals' + test_value = 'dvrnopuzoaczdpncjatn' self.instance.locationGroupName = test_value self.assertEqual(self.instance.locationGroupName, test_value) @@ -55,7 +56,7 @@ def test_locationGroupDesc_property(self): """ Test locationGroupDesc property """ - test_value = 'ggwvrbpdguicauubqwcy' + test_value = 'cqpqnvsnylvpmghokjfj' self.instance.locationGroupDesc = test_value self.assertEqual(self.instance.locationGroupDesc, test_value) @@ -63,7 +64,7 @@ def test_locationGroupUrl_property(self): """ Test locationGroupUrl property """ - test_value = 'tbupmeyrjhnszlvgxjgu' + test_value = 'gczugwjrvtentfmhsond' self.instance.locationGroupUrl = test_value self.assertEqual(self.instance.locationGroupUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroupstores.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroupstores.py index 55653b9..6f9388c 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroupstores.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_locationgroupstores.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.locationgroupstores import LocationGroupStores + class Test_LocationGroupStores(unittest.TestCase): """ Test case for LocationGroupStores @@ -27,9 +28,9 @@ def create_instance(): Create instance of LocationGroupStores for testing """ instance = LocationGroupStores( - locationGroupStoreId='xdsoytqjpyrvlysfncgu', - locationGroupId='ysswxsogpbiuisitrygp', - storeId='tlvtelpsorhrskowlwkp' + locationGroupStoreId='ahntjblcukfxrjrwtudc', + locationGroupId='mdkkfhjapxnxfmnxclsb', + storeId='lovkanhdbhokunqkcbzu' ) return instance @@ -38,7 +39,7 @@ def test_locationGroupStoreId_property(self): """ Test locationGroupStoreId property """ - test_value = 'xdsoytqjpyrvlysfncgu' + test_value = 'ahntjblcukfxrjrwtudc' self.instance.locationGroupStoreId = test_value self.assertEqual(self.instance.locationGroupStoreId, test_value) @@ -46,7 +47,7 @@ def test_locationGroupId_property(self): """ Test locationGroupId property """ - test_value = 'ysswxsogpbiuisitrygp' + test_value = 'mdkkfhjapxnxfmnxclsb' self.instance.locationGroupId = test_value self.assertEqual(self.instance.locationGroupId, test_value) @@ -54,7 +55,7 @@ def test_storeId_property(self): """ Test storeId property """ - test_value = 'tlvtelpsorhrskowlwkp' + test_value = 'lovkanhdbhokunqkcbzu' self.instance.storeId = test_value self.assertEqual(self.instance.storeId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_networks.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_networks.py index a77923b..1678352 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_networks.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_networks.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.networks import Networks + class Test_Networks(unittest.TestCase): """ Test case for Networks @@ -27,10 +28,10 @@ def create_instance(): Create instance of Networks for testing """ instance = Networks( - networkId='xnurkeurwhpeddoyugnk', - networkName='yexhdoojtyoiauwncgyq', - networkDesc='hglhgjwifhscbspgdtsw', - networkUrl='ukgbkvcxujynuxhudwnb' + networkId='veikseoaoxpovbdxsimj', + networkName='mmwznvmrswmnevmaijrd', + networkDesc='aawsvkpkvuyytwximukt', + networkUrl='lrsafplqzskbjxtcyisi' ) return instance @@ -39,7 +40,7 @@ def test_networkId_property(self): """ Test networkId property """ - test_value = 'xnurkeurwhpeddoyugnk' + test_value = 'veikseoaoxpovbdxsimj' self.instance.networkId = test_value self.assertEqual(self.instance.networkId, test_value) @@ -47,7 +48,7 @@ def test_networkName_property(self): """ Test networkName property """ - test_value = 'yexhdoojtyoiauwncgyq' + test_value = 'mmwznvmrswmnevmaijrd' self.instance.networkName = test_value self.assertEqual(self.instance.networkName, test_value) @@ -55,7 +56,7 @@ def test_networkDesc_property(self): """ Test networkDesc property """ - test_value = 'hglhgjwifhscbspgdtsw' + test_value = 'aawsvkpkvuyytwximukt' self.instance.networkDesc = test_value self.assertEqual(self.instance.networkDesc, test_value) @@ -63,7 +64,7 @@ def test_networkUrl_property(self): """ Test networkUrl property """ - test_value = 'ukgbkvcxujynuxhudwnb' + test_value = 'lrsafplqzskbjxtcyisi' self.instance.networkUrl = test_value self.assertEqual(self.instance.networkUrl, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_pathways.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_pathways.py index 4980671..954705e 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_pathways.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_pathways.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.pathways import Pathways + class Test_Pathways(unittest.TestCase): """ Test case for Pathways @@ -27,18 +28,18 @@ def create_instance(): Create instance of Pathways for testing """ instance = Pathways( - pathwayId='ncczfqfxmvpiyqbvduut', - fromStopId='tlwjglaugocmayhomoak', - toStopId='nrpcrfgqmrqexmhvjrkk', - pathwayMode=int(58), - isBidirectional=int(25), - length=float(97.24756695801547), - traversalTime=int(23), - stairCount=int(84), - maxSlope=float(97.3590036957665), - minWidth=float(33.23002239778553), - signpostedAs='rnnkanrcmllnqetkbfdm', - reversedSignpostedAs='idglnepwjwwvezqpnpof' + pathwayId='pohchezjmtfxrfcsxnsf', + fromStopId='luuavbyabsmhddlbqseg', + toStopId='ccmrfylxavaurrjarrnj', + pathwayMode=int(17), + isBidirectional=int(34), + length=float(11.666832648412395), + traversalTime=int(35), + stairCount=int(65), + maxSlope=float(11.160362450082618), + minWidth=float(29.954969450484846), + signpostedAs='uzkpfdsthchvaobeczwp', + reversedSignpostedAs='mubgfnwvfpnkxtkotvkg' ) return instance @@ -47,7 +48,7 @@ def test_pathwayId_property(self): """ Test pathwayId property """ - test_value = 'ncczfqfxmvpiyqbvduut' + test_value = 'pohchezjmtfxrfcsxnsf' self.instance.pathwayId = test_value self.assertEqual(self.instance.pathwayId, test_value) @@ -55,7 +56,7 @@ def test_fromStopId_property(self): """ Test fromStopId property """ - test_value = 'tlwjglaugocmayhomoak' + test_value = 'luuavbyabsmhddlbqseg' self.instance.fromStopId = test_value self.assertEqual(self.instance.fromStopId, test_value) @@ -63,7 +64,7 @@ def test_toStopId_property(self): """ Test toStopId property """ - test_value = 'nrpcrfgqmrqexmhvjrkk' + test_value = 'ccmrfylxavaurrjarrnj' self.instance.toStopId = test_value self.assertEqual(self.instance.toStopId, test_value) @@ -71,7 +72,7 @@ def test_pathwayMode_property(self): """ Test pathwayMode property """ - test_value = int(58) + test_value = int(17) self.instance.pathwayMode = test_value self.assertEqual(self.instance.pathwayMode, test_value) @@ -79,7 +80,7 @@ def test_isBidirectional_property(self): """ Test isBidirectional property """ - test_value = int(25) + test_value = int(34) self.instance.isBidirectional = test_value self.assertEqual(self.instance.isBidirectional, test_value) @@ -87,7 +88,7 @@ def test_length_property(self): """ Test length property """ - test_value = float(97.24756695801547) + test_value = float(11.666832648412395) self.instance.length = test_value self.assertEqual(self.instance.length, test_value) @@ -95,7 +96,7 @@ def test_traversalTime_property(self): """ Test traversalTime property """ - test_value = int(23) + test_value = int(35) self.instance.traversalTime = test_value self.assertEqual(self.instance.traversalTime, test_value) @@ -103,7 +104,7 @@ def test_stairCount_property(self): """ Test stairCount property """ - test_value = int(84) + test_value = int(65) self.instance.stairCount = test_value self.assertEqual(self.instance.stairCount, test_value) @@ -111,7 +112,7 @@ def test_maxSlope_property(self): """ Test maxSlope property """ - test_value = float(97.3590036957665) + test_value = float(11.160362450082618) self.instance.maxSlope = test_value self.assertEqual(self.instance.maxSlope, test_value) @@ -119,7 +120,7 @@ def test_minWidth_property(self): """ Test minWidth property """ - test_value = float(33.23002239778553) + test_value = float(29.954969450484846) self.instance.minWidth = test_value self.assertEqual(self.instance.minWidth, test_value) @@ -127,7 +128,7 @@ def test_signpostedAs_property(self): """ Test signpostedAs property """ - test_value = 'rnnkanrcmllnqetkbfdm' + test_value = 'uzkpfdsthchvaobeczwp' self.instance.signpostedAs = test_value self.assertEqual(self.instance.signpostedAs, test_value) @@ -135,7 +136,7 @@ def test_reversedSignpostedAs_property(self): """ Test reversedSignpostedAs property """ - test_value = 'idglnepwjwwvezqpnpof' + test_value = 'mubgfnwvfpnkxtkotvkg' self.instance.reversedSignpostedAs = test_value self.assertEqual(self.instance.reversedSignpostedAs, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routenetworks.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routenetworks.py index e9e51d9..589d6a4 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routenetworks.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routenetworks.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.routenetworks import RouteNetworks + class Test_RouteNetworks(unittest.TestCase): """ Test case for RouteNetworks @@ -27,9 +28,9 @@ def create_instance(): Create instance of RouteNetworks for testing """ instance = RouteNetworks( - routeNetworkId='tfxlwmwjisqmpqrwjhny', - routeId='sguuqhxupbwtfvyvnvfu', - networkId='erkydgrinqnyoyrqkdvt' + routeNetworkId='lbpbmrsqzamoplzztbak', + routeId='dkisralwzfmaqhfoupqx', + networkId='vvcbnmrxhahzrfzmaeet' ) return instance @@ -38,7 +39,7 @@ def test_routeNetworkId_property(self): """ Test routeNetworkId property """ - test_value = 'tfxlwmwjisqmpqrwjhny' + test_value = 'lbpbmrsqzamoplzztbak' self.instance.routeNetworkId = test_value self.assertEqual(self.instance.routeNetworkId, test_value) @@ -46,7 +47,7 @@ def test_routeId_property(self): """ Test routeId property """ - test_value = 'sguuqhxupbwtfvyvnvfu' + test_value = 'dkisralwzfmaqhfoupqx' self.instance.routeId = test_value self.assertEqual(self.instance.routeId, test_value) @@ -54,7 +55,7 @@ def test_networkId_property(self): """ Test networkId property """ - test_value = 'erkydgrinqnyoyrqkdvt' + test_value = 'vvcbnmrxhahzrfzmaeet' self.instance.networkId = test_value self.assertEqual(self.instance.networkId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routes.py index 02ce830..4a579d9 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_routes.py @@ -9,10 +9,11 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedstatic.routes import Routes -from test_gtfs_rt_producer_data_generaltransitfeedstatic_routetype import Test_RouteType from test_gtfs_rt_producer_data_generaltransitfeedstatic_continuousdropoff import Test_ContinuousDropOff +from test_gtfs_rt_producer_data_generaltransitfeedstatic_routetype import Test_RouteType from test_gtfs_rt_producer_data_generaltransitfeedstatic_continuouspickup import Test_ContinuousPickup + class Test_Routes(unittest.TestCase): """ Test case for Routes @@ -30,19 +31,19 @@ def create_instance(): Create instance of Routes for testing """ instance = Routes( - routeId='khtwstgrvxtnnyrqxuop', - agencyId='xsyechecyvweqybyaizt', - routeShortName='yxwfnocgwicqnmuvtopd', - routeLongName='ixccibbpjsmwyxqsxykl', - routeDesc='alqqgjjltswhsxhcylfb', + routeId='txcwbtfxpexbrhobrjpp', + agencyId='torcsxysxlefpuqnyglk', + routeShortName='archwdwgkwbcmmtwtqma', + routeLongName='qyytldoykhfaadsaxgsx', + routeDesc='moisytwbuyrewzulfctj', routeType=Test_RouteType.create_instance(), - routeUrl='xzbieevtyprndfirjdpv', - routeColor='ulkcevhbsbncjasfbins', - routeTextColor='rttubzskbiszonpuhqmu', - routeSortOrder=int(32), + routeUrl='bniejdotuwkvutvyvglv', + routeColor='ljuvwbbapgsuybjkblfy', + routeTextColor='gcbtergkmnicbimufjvm', + routeSortOrder=int(30), continuousPickup=Test_ContinuousPickup.create_instance(), continuousDropOff=Test_ContinuousDropOff.create_instance(), - networkId='oxuldrxkfscalkfkwpmy' + networkId='rhfolkfgduuxyrajlgqo' ) return instance @@ -51,7 +52,7 @@ def test_routeId_property(self): """ Test routeId property """ - test_value = 'khtwstgrvxtnnyrqxuop' + test_value = 'txcwbtfxpexbrhobrjpp' self.instance.routeId = test_value self.assertEqual(self.instance.routeId, test_value) @@ -59,7 +60,7 @@ def test_agencyId_property(self): """ Test agencyId property """ - test_value = 'xsyechecyvweqybyaizt' + test_value = 'torcsxysxlefpuqnyglk' self.instance.agencyId = test_value self.assertEqual(self.instance.agencyId, test_value) @@ -67,7 +68,7 @@ def test_routeShortName_property(self): """ Test routeShortName property """ - test_value = 'yxwfnocgwicqnmuvtopd' + test_value = 'archwdwgkwbcmmtwtqma' self.instance.routeShortName = test_value self.assertEqual(self.instance.routeShortName, test_value) @@ -75,7 +76,7 @@ def test_routeLongName_property(self): """ Test routeLongName property """ - test_value = 'ixccibbpjsmwyxqsxykl' + test_value = 'qyytldoykhfaadsaxgsx' self.instance.routeLongName = test_value self.assertEqual(self.instance.routeLongName, test_value) @@ -83,7 +84,7 @@ def test_routeDesc_property(self): """ Test routeDesc property """ - test_value = 'alqqgjjltswhsxhcylfb' + test_value = 'moisytwbuyrewzulfctj' self.instance.routeDesc = test_value self.assertEqual(self.instance.routeDesc, test_value) @@ -99,7 +100,7 @@ def test_routeUrl_property(self): """ Test routeUrl property """ - test_value = 'xzbieevtyprndfirjdpv' + test_value = 'bniejdotuwkvutvyvglv' self.instance.routeUrl = test_value self.assertEqual(self.instance.routeUrl, test_value) @@ -107,7 +108,7 @@ def test_routeColor_property(self): """ Test routeColor property """ - test_value = 'ulkcevhbsbncjasfbins' + test_value = 'ljuvwbbapgsuybjkblfy' self.instance.routeColor = test_value self.assertEqual(self.instance.routeColor, test_value) @@ -115,7 +116,7 @@ def test_routeTextColor_property(self): """ Test routeTextColor property """ - test_value = 'rttubzskbiszonpuhqmu' + test_value = 'gcbtergkmnicbimufjvm' self.instance.routeTextColor = test_value self.assertEqual(self.instance.routeTextColor, test_value) @@ -123,7 +124,7 @@ def test_routeSortOrder_property(self): """ Test routeSortOrder property """ - test_value = int(32) + test_value = int(30) self.instance.routeSortOrder = test_value self.assertEqual(self.instance.routeSortOrder, test_value) @@ -147,7 +148,7 @@ def test_networkId_property(self): """ Test networkId property """ - test_value = 'oxuldrxkfscalkfkwpmy' + test_value = 'rhfolkfgduuxyrajlgqo' self.instance.networkId = test_value self.assertEqual(self.instance.networkId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_shapes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_shapes.py index 2b5cc52..80fa4bf 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_shapes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_shapes.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.shapes import Shapes + class Test_Shapes(unittest.TestCase): """ Test case for Shapes @@ -27,11 +28,11 @@ def create_instance(): Create instance of Shapes for testing """ instance = Shapes( - shapeId='syjipszpgohctkkuqhgt', - shapePtLat=float(25.30099856513074), - shapePtLon=float(63.30384579599435), - shapePtSequence=int(99), - shapeDistTraveled=float(21.771484451242472) + shapeId='axylcavqsovayyvefghx', + shapePtLat=float(37.73770684631462), + shapePtLon=float(84.84434094604721), + shapePtSequence=int(25), + shapeDistTraveled=float(94.33924334713187) ) return instance @@ -40,7 +41,7 @@ def test_shapeId_property(self): """ Test shapeId property """ - test_value = 'syjipszpgohctkkuqhgt' + test_value = 'axylcavqsovayyvefghx' self.instance.shapeId = test_value self.assertEqual(self.instance.shapeId, test_value) @@ -48,7 +49,7 @@ def test_shapePtLat_property(self): """ Test shapePtLat property """ - test_value = float(25.30099856513074) + test_value = float(37.73770684631462) self.instance.shapePtLat = test_value self.assertEqual(self.instance.shapePtLat, test_value) @@ -56,7 +57,7 @@ def test_shapePtLon_property(self): """ Test shapePtLon property """ - test_value = float(63.30384579599435) + test_value = float(84.84434094604721) self.instance.shapePtLon = test_value self.assertEqual(self.instance.shapePtLon, test_value) @@ -64,7 +65,7 @@ def test_shapePtSequence_property(self): """ Test shapePtSequence property """ - test_value = int(99) + test_value = int(25) self.instance.shapePtSequence = test_value self.assertEqual(self.instance.shapePtSequence, test_value) @@ -72,7 +73,7 @@ def test_shapeDistTraveled_property(self): """ Test shapeDistTraveled property """ - test_value = float(21.771484451242472) + test_value = float(94.33924334713187) self.instance.shapeDistTraveled = test_value self.assertEqual(self.instance.shapeDistTraveled, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stopareas.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stopareas.py index e7e3413..3048f0d 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stopareas.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stopareas.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.stopareas import StopAreas + class Test_StopAreas(unittest.TestCase): """ Test case for StopAreas @@ -27,9 +28,9 @@ def create_instance(): Create instance of StopAreas for testing """ instance = StopAreas( - stopAreaId='xruuibulaibglmyypdls', - stopId='chikveynmseelbnknvol', - areaId='wyuzjkoghnqgkvlscnnc' + stopAreaId='hvvicnkgoicsxotvjbpj', + stopId='lthsuooeclhrcjijjshc', + areaId='glzsrbvmdvpyglleeskh' ) return instance @@ -38,7 +39,7 @@ def test_stopAreaId_property(self): """ Test stopAreaId property """ - test_value = 'xruuibulaibglmyypdls' + test_value = 'hvvicnkgoicsxotvjbpj' self.instance.stopAreaId = test_value self.assertEqual(self.instance.stopAreaId, test_value) @@ -46,7 +47,7 @@ def test_stopId_property(self): """ Test stopId property """ - test_value = 'chikveynmseelbnknvol' + test_value = 'lthsuooeclhrcjijjshc' self.instance.stopId = test_value self.assertEqual(self.instance.stopId, test_value) @@ -54,7 +55,7 @@ def test_areaId_property(self): """ Test areaId property """ - test_value = 'wyuzjkoghnqgkvlscnnc' + test_value = 'glzsrbvmdvpyglleeskh' self.instance.areaId = test_value self.assertEqual(self.instance.areaId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stops.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stops.py index d75f3f9..df7415d 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stops.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stops.py @@ -9,8 +9,9 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedstatic.stops import Stops -from test_gtfs_rt_producer_data_generaltransitfeedstatic_locationtype import Test_LocationType from test_gtfs_rt_producer_data_generaltransitfeedstatic_wheelchairboarding import Test_WheelchairBoarding +from test_gtfs_rt_producer_data_generaltransitfeedstatic_locationtype import Test_LocationType + class Test_Stops(unittest.TestCase): """ @@ -29,21 +30,21 @@ def create_instance(): Create instance of Stops for testing """ instance = Stops( - stopId='ygelzavdoynttizcgskl', - stopCode='geveaivznoyqusqqmfsw', - stopName='bjzawhdagdzcqbqgsrhl', - ttsStopName='fiqoctnbgrbhqbxxmkmy', - stopDesc='ljgsaerawnntqevejzwi', - stopLat=float(13.65830986702946), - stopLon=float(86.15415069825245), - zoneId='ccaynhxasrjntmgregdx', - stopUrl='njqftyuhgosizrtpsuel', + stopId='kyhxqibvvupddmhltsjn', + stopCode='mwqfqdzkiesentxcssmu', + stopName='czbxilhppzrkznvtuqne', + ttsStopName='qcszkwtculmzvncszyut', + stopDesc='rvyxokbnyoqgwewrumyn', + stopLat=float(53.57772366090949), + stopLon=float(24.860355743303465), + zoneId='okeiqpjkytzelnesbcoi', + stopUrl='dloyefsjlvyytsvjqdys', locationType=Test_LocationType.create_instance(), - parentStation='msvuatzaffuldieiruuy', - stopTimezone='kinxxdzomshwpxtyodnv', + parentStation='cohsncpjxlsmixydwojh', + stopTimezone='pmxooqdxecfcbupbtzrs', wheelchairBoarding=Test_WheelchairBoarding.create_instance(), - levelId='yjparzsdtkvscoezsjhi', - platformCode='tretlpllemrwsnpxiqso' + levelId='qgikbojtujmhhgtkhzvx', + platformCode='hokmzcfwlrfxixfajxtl' ) return instance @@ -52,7 +53,7 @@ def test_stopId_property(self): """ Test stopId property """ - test_value = 'ygelzavdoynttizcgskl' + test_value = 'kyhxqibvvupddmhltsjn' self.instance.stopId = test_value self.assertEqual(self.instance.stopId, test_value) @@ -60,7 +61,7 @@ def test_stopCode_property(self): """ Test stopCode property """ - test_value = 'geveaivznoyqusqqmfsw' + test_value = 'mwqfqdzkiesentxcssmu' self.instance.stopCode = test_value self.assertEqual(self.instance.stopCode, test_value) @@ -68,7 +69,7 @@ def test_stopName_property(self): """ Test stopName property """ - test_value = 'bjzawhdagdzcqbqgsrhl' + test_value = 'czbxilhppzrkznvtuqne' self.instance.stopName = test_value self.assertEqual(self.instance.stopName, test_value) @@ -76,7 +77,7 @@ def test_ttsStopName_property(self): """ Test ttsStopName property """ - test_value = 'fiqoctnbgrbhqbxxmkmy' + test_value = 'qcszkwtculmzvncszyut' self.instance.ttsStopName = test_value self.assertEqual(self.instance.ttsStopName, test_value) @@ -84,7 +85,7 @@ def test_stopDesc_property(self): """ Test stopDesc property """ - test_value = 'ljgsaerawnntqevejzwi' + test_value = 'rvyxokbnyoqgwewrumyn' self.instance.stopDesc = test_value self.assertEqual(self.instance.stopDesc, test_value) @@ -92,7 +93,7 @@ def test_stopLat_property(self): """ Test stopLat property """ - test_value = float(13.65830986702946) + test_value = float(53.57772366090949) self.instance.stopLat = test_value self.assertEqual(self.instance.stopLat, test_value) @@ -100,7 +101,7 @@ def test_stopLon_property(self): """ Test stopLon property """ - test_value = float(86.15415069825245) + test_value = float(24.860355743303465) self.instance.stopLon = test_value self.assertEqual(self.instance.stopLon, test_value) @@ -108,7 +109,7 @@ def test_zoneId_property(self): """ Test zoneId property """ - test_value = 'ccaynhxasrjntmgregdx' + test_value = 'okeiqpjkytzelnesbcoi' self.instance.zoneId = test_value self.assertEqual(self.instance.zoneId, test_value) @@ -116,7 +117,7 @@ def test_stopUrl_property(self): """ Test stopUrl property """ - test_value = 'njqftyuhgosizrtpsuel' + test_value = 'dloyefsjlvyytsvjqdys' self.instance.stopUrl = test_value self.assertEqual(self.instance.stopUrl, test_value) @@ -132,7 +133,7 @@ def test_parentStation_property(self): """ Test parentStation property """ - test_value = 'msvuatzaffuldieiruuy' + test_value = 'cohsncpjxlsmixydwojh' self.instance.parentStation = test_value self.assertEqual(self.instance.parentStation, test_value) @@ -140,7 +141,7 @@ def test_stopTimezone_property(self): """ Test stopTimezone property """ - test_value = 'kinxxdzomshwpxtyodnv' + test_value = 'pmxooqdxecfcbupbtzrs' self.instance.stopTimezone = test_value self.assertEqual(self.instance.stopTimezone, test_value) @@ -156,7 +157,7 @@ def test_levelId_property(self): """ Test levelId property """ - test_value = 'yjparzsdtkvscoezsjhi' + test_value = 'qgikbojtujmhhgtkhzvx' self.instance.levelId = test_value self.assertEqual(self.instance.levelId, test_value) @@ -164,7 +165,7 @@ def test_platformCode_property(self): """ Test platformCode property """ - test_value = 'tretlpllemrwsnpxiqso' + test_value = 'hokmzcfwlrfxixfajxtl' self.instance.platformCode = test_value self.assertEqual(self.instance.platformCode, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stoptimes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stoptimes.py index c7144dc..f7f11be 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stoptimes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_stoptimes.py @@ -9,12 +9,13 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedstatic.stoptimes import StopTimes -from test_gtfs_rt_producer_data_generaltransitfeedstatic_continuousdropoff import Test_ContinuousDropOff from test_gtfs_rt_producer_data_generaltransitfeedstatic_timepoint import Test_Timepoint from test_gtfs_rt_producer_data_generaltransitfeedstatic_pickuptype import Test_PickupType +from test_gtfs_rt_producer_data_generaltransitfeedstatic_continuousdropoff import Test_ContinuousDropOff from test_gtfs_rt_producer_data_generaltransitfeedstatic_dropofftype import Test_DropOffType from test_gtfs_rt_producer_data_generaltransitfeedstatic_continuouspickup import Test_ContinuousPickup + class Test_StopTimes(unittest.TestCase): """ Test case for StopTimes @@ -32,17 +33,17 @@ def create_instance(): Create instance of StopTimes for testing """ instance = StopTimes( - tripId='kxqltkgfybcoqlnjjukg', - arrivalTime='jogfrhzsayymqdlfncba', - departureTime='wynodxhdzrlvbvhljkqx', - stopId='smvmehwizmcekkwvnywl', - stopSequence=int(33), - stopHeadsign='jwsyoixixjnxpdmolcgm', + tripId='ksotvevphvayhopfrtac', + arrivalTime='ebiucpzumxeccfeyrila', + departureTime='cfxsnvlfkmqnvnvzcdkh', + stopId='vpaxomwrwkceaermperi', + stopSequence=int(34), + stopHeadsign='nyqpyjrycfpfzppniptj', pickupType=Test_PickupType.create_instance(), dropOffType=Test_DropOffType.create_instance(), continuousPickup=Test_ContinuousPickup.create_instance(), continuousDropOff=Test_ContinuousDropOff.create_instance(), - shapeDistTraveled=float(4.277457202604884), + shapeDistTraveled=float(23.959564066857787), timepoint=Test_Timepoint.create_instance() ) return instance @@ -52,7 +53,7 @@ def test_tripId_property(self): """ Test tripId property """ - test_value = 'kxqltkgfybcoqlnjjukg' + test_value = 'ksotvevphvayhopfrtac' self.instance.tripId = test_value self.assertEqual(self.instance.tripId, test_value) @@ -60,7 +61,7 @@ def test_arrivalTime_property(self): """ Test arrivalTime property """ - test_value = 'jogfrhzsayymqdlfncba' + test_value = 'ebiucpzumxeccfeyrila' self.instance.arrivalTime = test_value self.assertEqual(self.instance.arrivalTime, test_value) @@ -68,7 +69,7 @@ def test_departureTime_property(self): """ Test departureTime property """ - test_value = 'wynodxhdzrlvbvhljkqx' + test_value = 'cfxsnvlfkmqnvnvzcdkh' self.instance.departureTime = test_value self.assertEqual(self.instance.departureTime, test_value) @@ -76,7 +77,7 @@ def test_stopId_property(self): """ Test stopId property """ - test_value = 'smvmehwizmcekkwvnywl' + test_value = 'vpaxomwrwkceaermperi' self.instance.stopId = test_value self.assertEqual(self.instance.stopId, test_value) @@ -84,7 +85,7 @@ def test_stopSequence_property(self): """ Test stopSequence property """ - test_value = int(33) + test_value = int(34) self.instance.stopSequence = test_value self.assertEqual(self.instance.stopSequence, test_value) @@ -92,7 +93,7 @@ def test_stopHeadsign_property(self): """ Test stopHeadsign property """ - test_value = 'jwsyoixixjnxpdmolcgm' + test_value = 'nyqpyjrycfpfzppniptj' self.instance.stopHeadsign = test_value self.assertEqual(self.instance.stopHeadsign, test_value) @@ -132,7 +133,7 @@ def test_shapeDistTraveled_property(self): """ Test shapeDistTraveled property """ - test_value = float(4.277457202604884) + test_value = float(23.959564066857787) self.instance.shapeDistTraveled = test_value self.assertEqual(self.instance.shapeDistTraveled, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_timeframes.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_timeframes.py index 2793074..f8b2471 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_timeframes.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_timeframes.py @@ -12,6 +12,7 @@ from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar import Test_Calendar from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates import Test_CalendarDates + class Test_Timeframes(unittest.TestCase): """ Test case for Timeframes @@ -29,9 +30,9 @@ def create_instance(): Create instance of Timeframes for testing """ instance = Timeframes( - timeframeGroupId='vpdgdylsmcmfimmpdseu', - startTime='drxjyjgbqwehmkiffamr', - endTime='mbyonlwqcsqfnokydnnh', + timeframeGroupId='eztdcirkdgljiwpgideb', + startTime='opgpjebgrhrkauqxxohe', + endTime='ifartiukhxrhpcisoxga', serviceDates=Test_Calendar.create_instance() ) return instance @@ -41,7 +42,7 @@ def test_timeframeGroupId_property(self): """ Test timeframeGroupId property """ - test_value = 'vpdgdylsmcmfimmpdseu' + test_value = 'eztdcirkdgljiwpgideb' self.instance.timeframeGroupId = test_value self.assertEqual(self.instance.timeframeGroupId, test_value) @@ -49,7 +50,7 @@ def test_startTime_property(self): """ Test startTime property """ - test_value = 'drxjyjgbqwehmkiffamr' + test_value = 'opgpjebgrhrkauqxxohe' self.instance.startTime = test_value self.assertEqual(self.instance.startTime, test_value) @@ -57,7 +58,7 @@ def test_endTime_property(self): """ Test endTime property """ - test_value = 'mbyonlwqcsqfnokydnnh' + test_value = 'ifartiukhxrhpcisoxga' self.instance.endTime = test_value self.assertEqual(self.instance.endTime, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_transfers.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_transfers.py index 3920e8c..fe7350b 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_transfers.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_transfers.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.transfers import Transfers + class Test_Transfers(unittest.TestCase): """ Test case for Transfers @@ -27,10 +28,10 @@ def create_instance(): Create instance of Transfers for testing """ instance = Transfers( - fromStopId='erxflrjofhxrdkrrmchc', - toStopId='tmmekkjhkpyhpddyfeua', - transferType=int(93), - minTransferTime=int(2) + fromStopId='zpvffixxsukcbbapkwaq', + toStopId='xkipwgtdzfkrvuctncdk', + transferType=int(98), + minTransferTime=int(77) ) return instance @@ -39,7 +40,7 @@ def test_fromStopId_property(self): """ Test fromStopId property """ - test_value = 'erxflrjofhxrdkrrmchc' + test_value = 'zpvffixxsukcbbapkwaq' self.instance.fromStopId = test_value self.assertEqual(self.instance.fromStopId, test_value) @@ -47,7 +48,7 @@ def test_toStopId_property(self): """ Test toStopId property """ - test_value = 'tmmekkjhkpyhpddyfeua' + test_value = 'xkipwgtdzfkrvuctncdk' self.instance.toStopId = test_value self.assertEqual(self.instance.toStopId, test_value) @@ -55,7 +56,7 @@ def test_transferType_property(self): """ Test transferType property """ - test_value = int(93) + test_value = int(98) self.instance.transferType = test_value self.assertEqual(self.instance.transferType, test_value) @@ -63,7 +64,7 @@ def test_minTransferTime_property(self): """ Test minTransferTime property """ - test_value = int(2) + test_value = int(77) self.instance.minTransferTime = test_value self.assertEqual(self.instance.minTransferTime, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_translations.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_translations.py index 37595ee..b5aa000 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_translations.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_translations.py @@ -10,6 +10,7 @@ from gtfs_rt_producer_data.generaltransitfeedstatic.translations import Translations + class Test_Translations(unittest.TestCase): """ Test case for Translations @@ -27,10 +28,10 @@ def create_instance(): Create instance of Translations for testing """ instance = Translations( - tableName='yknftywydzfsgkhkrjcr', - fieldName='mzzclrhafrklvvmeennl', - language='nmnhnxujktjszazvlyoe', - translation='tmsstuwwhniszwpvpzkq' + tableName='aanhizixqqpcfjufuqom', + fieldName='qwtvuaxuexmjiacvuhma', + language='hrtvteidgzibhlqybpgq', + translation='kcjmaskfeydtyoqxdwzk' ) return instance @@ -39,7 +40,7 @@ def test_tableName_property(self): """ Test tableName property """ - test_value = 'yknftywydzfsgkhkrjcr' + test_value = 'aanhizixqqpcfjufuqom' self.instance.tableName = test_value self.assertEqual(self.instance.tableName, test_value) @@ -47,7 +48,7 @@ def test_fieldName_property(self): """ Test fieldName property """ - test_value = 'mzzclrhafrklvvmeennl' + test_value = 'qwtvuaxuexmjiacvuhma' self.instance.fieldName = test_value self.assertEqual(self.instance.fieldName, test_value) @@ -55,7 +56,7 @@ def test_language_property(self): """ Test language property """ - test_value = 'nmnhnxujktjszazvlyoe' + test_value = 'hrtvteidgzibhlqybpgq' self.instance.language = test_value self.assertEqual(self.instance.language, test_value) @@ -63,7 +64,7 @@ def test_translation_property(self): """ Test translation property """ - test_value = 'tmsstuwwhniszwpvpzkq' + test_value = 'kcjmaskfeydtyoqxdwzk' self.instance.translation = test_value self.assertEqual(self.instance.translation, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_trips.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_trips.py index ad30671..7289ce2 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_trips.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_data/tests/test_gtfs_rt_producer_data_generaltransitfeedstatic_trips.py @@ -9,11 +9,12 @@ sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../src'.replace('/', os.sep)))) from gtfs_rt_producer_data.generaltransitfeedstatic.trips import Trips -from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar import Test_Calendar -from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates import Test_CalendarDates from test_gtfs_rt_producer_data_generaltransitfeedstatic_wheelchairaccessible import Test_WheelchairAccessible +from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendar import Test_Calendar from test_gtfs_rt_producer_data_generaltransitfeedstatic_directionid import Test_DirectionId from test_gtfs_rt_producer_data_generaltransitfeedstatic_bikesallowed import Test_BikesAllowed +from test_gtfs_rt_producer_data_generaltransitfeedstatic_calendardates import Test_CalendarDates + class Test_Trips(unittest.TestCase): """ @@ -32,15 +33,15 @@ def create_instance(): Create instance of Trips for testing """ instance = Trips( - routeId='qzqqtajjczwhyujonbsp', + routeId='jnkltylqdrbhkgwalqpm', serviceDates=Test_Calendar.create_instance(), - serviceExceptions=[Test_CalendarDates.create_instance()], - tripId='tghtthpadsnrynykmltt', - tripHeadsign='yzzfelgnfsphmrsvhxpm', - tripShortName='wiwnlylrdvbmrjsfagux', + serviceExceptions=[Test_CalendarDates.create_instance(), Test_CalendarDates.create_instance()], + tripId='hhdkbjxdqscfinwadzyi', + tripHeadsign='pnkvoidmlnzzepumdbic', + tripShortName='mipqouthkhusfpaaqnsx', directionId=Test_DirectionId.create_instance(), - blockId='hosulvqiuysgpokvrgte', - shapeId='vwgbycsbtjagolpwqtga', + blockId='bmkjrmlmeohgafbdxsux', + shapeId='zzwxmbrjfotcwlvbsgpx', wheelchairAccessible=Test_WheelchairAccessible.create_instance(), bikesAllowed=Test_BikesAllowed.create_instance() ) @@ -51,7 +52,7 @@ def test_routeId_property(self): """ Test routeId property """ - test_value = 'qzqqtajjczwhyujonbsp' + test_value = 'jnkltylqdrbhkgwalqpm' self.instance.routeId = test_value self.assertEqual(self.instance.routeId, test_value) @@ -67,7 +68,7 @@ def test_serviceExceptions_property(self): """ Test serviceExceptions property """ - test_value = [Test_CalendarDates.create_instance()] + test_value = [Test_CalendarDates.create_instance(), Test_CalendarDates.create_instance()] self.instance.serviceExceptions = test_value self.assertEqual(self.instance.serviceExceptions, test_value) @@ -75,7 +76,7 @@ def test_tripId_property(self): """ Test tripId property """ - test_value = 'tghtthpadsnrynykmltt' + test_value = 'hhdkbjxdqscfinwadzyi' self.instance.tripId = test_value self.assertEqual(self.instance.tripId, test_value) @@ -83,7 +84,7 @@ def test_tripHeadsign_property(self): """ Test tripHeadsign property """ - test_value = 'yzzfelgnfsphmrsvhxpm' + test_value = 'pnkvoidmlnzzepumdbic' self.instance.tripHeadsign = test_value self.assertEqual(self.instance.tripHeadsign, test_value) @@ -91,7 +92,7 @@ def test_tripShortName_property(self): """ Test tripShortName property """ - test_value = 'wiwnlylrdvbmrjsfagux' + test_value = 'mipqouthkhusfpaaqnsx' self.instance.tripShortName = test_value self.assertEqual(self.instance.tripShortName, test_value) @@ -107,7 +108,7 @@ def test_blockId_property(self): """ Test blockId property """ - test_value = 'hosulvqiuysgpokvrgte' + test_value = 'bmkjrmlmeohgafbdxsux' self.instance.blockId = test_value self.assertEqual(self.instance.blockId, test_value) @@ -115,7 +116,7 @@ def test_shapeId_property(self): """ Test shapeId property """ - test_value = 'vwgbycsbtjagolpwqtga' + test_value = 'zzwxmbrjfotcwlvbsgpx' self.instance.shapeId = test_value self.assertEqual(self.instance.shapeId, test_value) diff --git a/gtfs/gtfs_rt_producer/gtfs_rt_producer_kafka_producer/src/gtfs_rt_producer_kafka_producer/producer.py b/gtfs/gtfs_rt_producer/gtfs_rt_producer_kafka_producer/src/gtfs_rt_producer_kafka_producer/producer.py index ab11ec9..d77f14a 100644 --- a/gtfs/gtfs_rt_producer/gtfs_rt_producer_kafka_producer/src/gtfs_rt_producer_kafka_producer/producer.py +++ b/gtfs/gtfs_rt_producer/gtfs_rt_producer_kafka_producer/src/gtfs_rt_producer_kafka_producer/producer.py @@ -89,7 +89,7 @@ async def send_general_transit_feed_real_time_vehicle_vehicle_position(self,_fee attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -99,55 +99,6 @@ async def send_general_transit_feed_real_time_vehicle_vehicle_position(self,_fee if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedRealTimeEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_real_time_trip_trip_update(self,_feedurl : str, _agencyid : str, data: TripUpdate, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, TripUpdate], str]=None) -> None: """ @@ -171,7 +122,7 @@ async def send_general_transit_feed_real_time_trip_trip_update(self,_feedurl : s attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -181,55 +132,6 @@ async def send_general_transit_feed_real_time_trip_trip_update(self,_feedurl : s if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedRealTimeEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_real_time_alert_alert(self,_feedurl : str, _agencyid : str, data: Alert, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Alert], str]=None) -> None: """ @@ -253,7 +155,7 @@ async def send_general_transit_feed_real_time_alert_alert(self,_feedurl : str, _ attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -263,6 +165,7 @@ async def send_general_transit_feed_real_time_alert_alert(self,_feedurl : str, _ if flush_producer: self.producer.flush() + @classmethod def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: """ @@ -364,7 +267,7 @@ async def send_general_transit_feed_static_agency(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -374,55 +277,6 @@ async def send_general_transit_feed_static_agency(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_areas(self,_feedurl : str, _agencyid : str, data: Areas, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Areas], str]=None) -> None: """ @@ -446,7 +300,7 @@ async def send_general_transit_feed_static_areas(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -456,55 +310,6 @@ async def send_general_transit_feed_static_areas(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_attributions(self,_feedurl : str, _agencyid : str, data: Attributions, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Attributions], str]=None) -> None: """ @@ -528,7 +333,7 @@ async def send_general_transit_feed_static_attributions(self,_feedurl : str, _ag attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -538,55 +343,6 @@ async def send_general_transit_feed_static_attributions(self,_feedurl : str, _ag if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_booking_rules(self,_feedurl : str, _agencyid : str, data: BookingRules, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, BookingRules], str]=None) -> None: """ @@ -610,7 +366,7 @@ async def send_general_transit_feed_booking_rules(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -620,59 +376,10 @@ async def send_general_transit_feed_booking_rules(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: + + async def send_general_transit_feed_static_fare_attributes(self,_feedurl : str, _agencyid : str, data: FareAttributes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareAttributes], str]=None) -> None: """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - - - async def send_general_transit_feed_static_fare_attributes(self,_feedurl : str, _agencyid : str, data: FareAttributes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareAttributes], str]=None) -> None: - """ - Sends the 'GeneralTransitFeedStatic.FareAttributes' event to the Kafka topic + Sends the 'GeneralTransitFeedStatic.FareAttributes' event to the Kafka topic Args: _feedurl(str): Value for placeholder feedurl in attribute source @@ -692,7 +399,7 @@ async def send_general_transit_feed_static_fare_attributes(self,_feedurl : str, attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -702,55 +409,6 @@ async def send_general_transit_feed_static_fare_attributes(self,_feedurl : str, if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_fare_leg_rules(self,_feedurl : str, _agencyid : str, data: FareLegRules, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareLegRules], str]=None) -> None: """ @@ -774,7 +432,7 @@ async def send_general_transit_feed_static_fare_leg_rules(self,_feedurl : str, _ attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -784,55 +442,6 @@ async def send_general_transit_feed_static_fare_leg_rules(self,_feedurl : str, _ if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_fare_media(self,_feedurl : str, _agencyid : str, data: FareMedia, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareMedia], str]=None) -> None: """ @@ -856,7 +465,7 @@ async def send_general_transit_feed_static_fare_media(self,_feedurl : str, _agen attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -866,55 +475,6 @@ async def send_general_transit_feed_static_fare_media(self,_feedurl : str, _agen if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_fare_products(self,_feedurl : str, _agencyid : str, data: FareProducts, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareProducts], str]=None) -> None: """ @@ -938,7 +498,7 @@ async def send_general_transit_feed_static_fare_products(self,_feedurl : str, _a attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -948,55 +508,6 @@ async def send_general_transit_feed_static_fare_products(self,_feedurl : str, _a if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_fare_rules(self,_feedurl : str, _agencyid : str, data: FareRules, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareRules], str]=None) -> None: """ @@ -1020,7 +531,7 @@ async def send_general_transit_feed_static_fare_rules(self,_feedurl : str, _agen attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1030,59 +541,10 @@ async def send_general_transit_feed_static_fare_rules(self,_feedurl : str, _agen if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: + + async def send_general_transit_feed_static_fare_transfer_rules(self,_feedurl : str, _agencyid : str, data: FareTransferRules, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareTransferRules], str]=None) -> None: """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - - - async def send_general_transit_feed_static_fare_transfer_rules(self,_feedurl : str, _agencyid : str, data: FareTransferRules, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FareTransferRules], str]=None) -> None: - """ - Sends the 'GeneralTransitFeedStatic.FareTransferRules' event to the Kafka topic + Sends the 'GeneralTransitFeedStatic.FareTransferRules' event to the Kafka topic Args: _feedurl(str): Value for placeholder feedurl in attribute source @@ -1102,7 +564,7 @@ async def send_general_transit_feed_static_fare_transfer_rules(self,_feedurl : s attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1112,55 +574,6 @@ async def send_general_transit_feed_static_fare_transfer_rules(self,_feedurl : s if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_feed_info(self,_feedurl : str, _agencyid : str, data: FeedInfo, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, FeedInfo], str]=None) -> None: """ @@ -1184,7 +597,7 @@ async def send_general_transit_feed_static_feed_info(self,_feedurl : str, _agenc attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1194,55 +607,6 @@ async def send_general_transit_feed_static_feed_info(self,_feedurl : str, _agenc if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_frequencies(self,_feedurl : str, _agencyid : str, data: Frequencies, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Frequencies], str]=None) -> None: """ @@ -1266,7 +630,7 @@ async def send_general_transit_feed_static_frequencies(self,_feedurl : str, _age attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1276,55 +640,6 @@ async def send_general_transit_feed_static_frequencies(self,_feedurl : str, _age if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_levels(self,_feedurl : str, _agencyid : str, data: Levels, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Levels], str]=None) -> None: """ @@ -1348,7 +663,7 @@ async def send_general_transit_feed_static_levels(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1358,55 +673,6 @@ async def send_general_transit_feed_static_levels(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_location_geo_json(self,_feedurl : str, _agencyid : str, data: LocationGeoJson, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, LocationGeoJson], str]=None) -> None: """ @@ -1430,7 +696,7 @@ async def send_general_transit_feed_static_location_geo_json(self,_feedurl : str attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1440,68 +706,19 @@ async def send_general_transit_feed_static_location_geo_json(self,_feedurl : str if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: + + async def send_general_transit_feed_static_location_groups(self,_feedurl : str, _agencyid : str, data: LocationGroups, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, LocationGroups], str]=None) -> None: """ - Parse the connection string and extract bootstrap server, topic name, username, and password. + Sends the 'GeneralTransitFeedStatic.LocationGroups' event to the Kafka topic Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - - - async def send_general_transit_feed_static_location_groups(self,_feedurl : str, _agencyid : str, data: LocationGroups, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, LocationGroups], str]=None) -> None: - """ - Sends the 'GeneralTransitFeedStatic.LocationGroups' event to the Kafka topic - - Args: - _feedurl(str): Value for placeholder feedurl in attribute source - _agencyid(str): Value for placeholder agencyid in attribute subject - data: (LocationGroups): The event data to be sent - content_type (str): The content type that the event data shall be sent with - flush_producer(bool): Whether to flush the producer after sending the event (default: True) - key_mapper(Callable[[CloudEvent, LocationGroups], str]): A function to map the CloudEvent contents to a Kafka key (default: None). - The default key mapper maps the CloudEvent type, source, and subject to the Kafka key + _feedurl(str): Value for placeholder feedurl in attribute source + _agencyid(str): Value for placeholder agencyid in attribute subject + data: (LocationGroups): The event data to be sent + content_type (str): The content type that the event data shall be sent with + flush_producer(bool): Whether to flush the producer after sending the event (default: True) + key_mapper(Callable[[CloudEvent, LocationGroups], str]): A function to map the CloudEvent contents to a Kafka key (default: None). + The default key mapper maps the CloudEvent type, source, and subject to the Kafka key """ attributes = { "specversion":"1.0", @@ -1512,7 +729,7 @@ async def send_general_transit_feed_static_location_groups(self,_feedurl : str, attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1522,55 +739,6 @@ async def send_general_transit_feed_static_location_groups(self,_feedurl : str, if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_location_group_stores(self,_feedurl : str, _agencyid : str, data: LocationGroupStores, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, LocationGroupStores], str]=None) -> None: """ @@ -1594,7 +762,7 @@ async def send_general_transit_feed_static_location_group_stores(self,_feedurl : attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1604,55 +772,6 @@ async def send_general_transit_feed_static_location_group_stores(self,_feedurl : if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_networks(self,_feedurl : str, _agencyid : str, data: Networks, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Networks], str]=None) -> None: """ @@ -1676,7 +795,7 @@ async def send_general_transit_feed_static_networks(self,_feedurl : str, _agency attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1686,55 +805,6 @@ async def send_general_transit_feed_static_networks(self,_feedurl : str, _agency if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_pathways(self,_feedurl : str, _agencyid : str, data: Pathways, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Pathways], str]=None) -> None: """ @@ -1758,7 +828,7 @@ async def send_general_transit_feed_static_pathways(self,_feedurl : str, _agency attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1768,55 +838,6 @@ async def send_general_transit_feed_static_pathways(self,_feedurl : str, _agency if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_route_networks(self,_feedurl : str, _agencyid : str, data: RouteNetworks, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, RouteNetworks], str]=None) -> None: """ @@ -1840,7 +861,7 @@ async def send_general_transit_feed_static_route_networks(self,_feedurl : str, _ attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1850,55 +871,6 @@ async def send_general_transit_feed_static_route_networks(self,_feedurl : str, _ if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_routes(self,_feedurl : str, _agencyid : str, data: Routes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Routes], str]=None) -> None: """ @@ -1922,7 +894,7 @@ async def send_general_transit_feed_static_routes(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -1932,55 +904,6 @@ async def send_general_transit_feed_static_routes(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_shapes(self,_feedurl : str, _agencyid : str, data: Shapes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Shapes], str]=None) -> None: """ @@ -2004,7 +927,7 @@ async def send_general_transit_feed_static_shapes(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2014,55 +937,6 @@ async def send_general_transit_feed_static_shapes(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_stop_areas(self,_feedurl : str, _agencyid : str, data: StopAreas, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, StopAreas], str]=None) -> None: """ @@ -2084,66 +958,17 @@ async def send_general_transit_feed_static_stop_areas(self,_feedurl : str, _agen "subject":"{agencyid}".format(agencyid = _agencyid) } attributes["datacontenttype"] = content_type - event = CloudEvent.create(attributes, data) - if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) - message.headers[b"content-type"] = b"application/cloudevents+json" - else: - content_type = "application/json" - event["content-type"] = content_type - message = to_binary(event, data_marshaller=lambda x: x.to_byte_array(content_type), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) - self.producer.produce(self.topic, key=message.key, value=message.value, headers=message.headers) - if flush_producer: - self.producer.flush() - - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) + event = CloudEvent.create(attributes, data) + if self.content_mode == "structured": + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message.headers[b"content-type"] = b"application/cloudevents+json" + else: + content_type = "application/json" + event["content-type"] = content_type + message = to_binary(event, data_marshaller=lambda x: x.to_byte_array(content_type), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + self.producer.produce(self.topic, key=message.key, value=message.value, headers=message.headers) + if flush_producer: + self.producer.flush() async def send_general_transit_feed_static_stops(self,_feedurl : str, _agencyid : str, data: Stops, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Stops], str]=None) -> None: @@ -2168,7 +993,7 @@ async def send_general_transit_feed_static_stops(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2178,55 +1003,6 @@ async def send_general_transit_feed_static_stops(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_stop_times(self,_feedurl : str, _agencyid : str, data: StopTimes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, StopTimes], str]=None) -> None: """ @@ -2250,7 +1026,7 @@ async def send_general_transit_feed_static_stop_times(self,_feedurl : str, _agen attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2260,55 +1036,6 @@ async def send_general_transit_feed_static_stop_times(self,_feedurl : str, _agen if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_timeframes(self,_feedurl : str, _agencyid : str, data: Timeframes, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Timeframes], str]=None) -> None: """ @@ -2332,7 +1059,7 @@ async def send_general_transit_feed_static_timeframes(self,_feedurl : str, _agen attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2342,55 +1069,6 @@ async def send_general_transit_feed_static_timeframes(self,_feedurl : str, _agen if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_transfers(self,_feedurl : str, _agencyid : str, data: Transfers, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Transfers], str]=None) -> None: """ @@ -2414,7 +1092,7 @@ async def send_general_transit_feed_static_transfers(self,_feedurl : str, _agenc attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2424,55 +1102,6 @@ async def send_general_transit_feed_static_transfers(self,_feedurl : str, _agenc if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_translations(self,_feedurl : str, _agencyid : str, data: Translations, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Translations], str]=None) -> None: """ @@ -2496,7 +1125,7 @@ async def send_general_transit_feed_static_translations(self,_feedurl : str, _ag attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2506,55 +1135,6 @@ async def send_general_transit_feed_static_translations(self,_feedurl : str, _ag if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'GeneralTransitFeedStaticEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_general_transit_feed_static_trips(self,_feedurl : str, _agencyid : str, data: Trips, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, Trips], str]=None) -> None: """ @@ -2578,7 +1158,7 @@ async def send_general_transit_feed_static_trips(self,_feedurl : str, _agencyid attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -2588,6 +1168,7 @@ async def send_general_transit_feed_static_trips(self,_feedurl : str, _agencyid if flush_producer: self.producer.flush() + @classmethod def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: """ diff --git a/gtfs/xreg/create-kql-script.ps1 b/gtfs/kql/create-kql-script.ps1 similarity index 95% rename from gtfs/xreg/create-kql-script.ps1 rename to gtfs/kql/create-kql-script.ps1 index d3a11e5..1afae9d 100644 --- a/gtfs/xreg/create-kql-script.ps1 +++ b/gtfs/kql/create-kql-script.ps1 @@ -1,6 +1,6 @@ $scriptPath = Split-Path -Parent $PSCommandPath -$jsonFiles = Get-ChildItem -Path "$scriptPath/gtfs-static" -Filter "*.avsc" | Select-Object -ExpandProperty FullName -$gtfsRtFiles = Get-ChildItem -Path "$scriptPath" -Filter "gtfs-rt-*.avsc" | Select-Object -ExpandProperty FullName +$jsonFiles = Get-ChildItem -Path "$scriptPath/../xreg/gtfs-static" -Filter "*.avsc" | Select-Object -ExpandProperty FullName +$gtfsRtFiles = Get-ChildItem -Path "$scriptPath/../xreg/" -Filter "gtfs-rt-*.avsc" | Select-Object -ExpandProperty FullName $jsonFiles += $gtfsRtFiles $outputFile = ".schemas.avsc" diff --git a/gtfs/xreg/gtfs.kql b/gtfs/kql/gtfs.kql similarity index 97% rename from gtfs/xreg/gtfs.kql rename to gtfs/kql/gtfs.kql index 664fe4a..52c9fec 100644 --- a/gtfs/xreg/gtfs.kql +++ b/gtfs/kql/gtfs.kql @@ -2789,10 +2789,10 @@ stop_schedule_relationship = tostring(stop_time_update.schedule_relationship) | extend arrival_delay = toint(arrival.delay), - arrival_time = unixtime_seconds_todatetime(arrival.time), + arrival_time = unixtime_seconds_todatetime(toint(arrival.['time'])), arrival_uncertainty = toint(arrival.uncertainty), departure_delay = toint(departure.delay), - departure_time = unixtime_seconds_todatetime(departure.time), + departure_time = unixtime_seconds_todatetime(toint(departure.['time'])), departure_uncertainty = toint(departure.uncertainty) | extend trip_id = tostring(trip.trip_id), diff --git a/gtfs/xreg/gtfs.xreg.json b/gtfs/xreg/gtfs.xreg.json index 7362036..318395a 100644 --- a/gtfs/xreg/gtfs.xreg.json +++ b/gtfs/xreg/gtfs.xreg.json @@ -12,9 +12,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedRealTime/schemas/GeneralTransitFeedRealTime.Vehicle.VehiclePosition", - "createdat": "2024-09-14T19:33:53.276277", + "createdat": "2024-09-18T14:18:22.193499", "epoch": 0, - "modifiedat": "2024-09-14T19:33:53.276277", + "modifiedat": "2024-09-18T14:18:22.193499", "metadata": { "specversion": { "name": "specversion", @@ -51,9 +51,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedRealTime/schemas/GeneralTransitFeedRealTime.Trip.TripUpdate", - "createdat": "2024-09-14T19:33:56.509005", + "createdat": "2024-09-18T14:18:25.396108", "epoch": 0, - "modifiedat": "2024-09-14T19:33:56.509005", + "modifiedat": "2024-09-18T14:18:25.396108", "metadata": { "specversion": { "name": "specversion", @@ -90,9 +90,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedRealTime/schemas/GeneralTransitFeedRealTime.Alert.Alert", - "createdat": "2024-09-14T19:33:59.755279", + "createdat": "2024-09-18T14:18:28.567740", "epoch": 0, - "modifiedat": "2024-09-14T19:33:59.755279", + "modifiedat": "2024-09-18T14:18:28.567740", "metadata": { "specversion": { "name": "specversion", @@ -124,9 +124,9 @@ } } }, - "createdat": "2024-09-14T19:33:53.274259", + "createdat": "2024-09-18T14:18:22.191092", "epoch": 0, - "modifiedat": "2024-09-14T19:33:53.274259" + "modifiedat": "2024-09-18T14:18:22.191092" }, "GeneralTransitFeedStatic": { "id": "GeneralTransitFeedStatic", @@ -137,9 +137,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Agency", - "createdat": "2024-09-14T19:34:02.945459", + "createdat": "2024-09-18T14:18:31.834679", "epoch": 0, - "modifiedat": "2024-09-14T19:34:02.945459", + "modifiedat": "2024-09-18T14:18:31.834679", "metadata": { "specversion": { "name": "specversion", @@ -176,9 +176,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Areas", - "createdat": "2024-09-14T19:34:06.109457", + "createdat": "2024-09-18T14:18:35.115684", "epoch": 0, - "modifiedat": "2024-09-14T19:34:06.109457", + "modifiedat": "2024-09-18T14:18:35.115684", "metadata": { "specversion": { "name": "specversion", @@ -215,9 +215,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Attributions", - "createdat": "2024-09-14T19:34:09.322877", + "createdat": "2024-09-18T14:18:38.318441", "epoch": 0, - "modifiedat": "2024-09-14T19:34:09.322877", + "modifiedat": "2024-09-18T14:18:38.318441", "metadata": { "specversion": { "name": "specversion", @@ -254,9 +254,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeed.BookingRules", - "createdat": "2024-09-14T19:34:12.495400", + "createdat": "2024-09-18T14:18:41.536027", "epoch": 0, - "modifiedat": "2024-09-14T19:34:12.495400", + "modifiedat": "2024-09-18T14:18:41.536027", "metadata": { "specversion": { "name": "specversion", @@ -293,9 +293,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareAttributes", - "createdat": "2024-09-14T19:34:15.660243", + "createdat": "2024-09-18T14:18:44.864190", "epoch": 0, - "modifiedat": "2024-09-14T19:34:15.660243", + "modifiedat": "2024-09-18T14:18:44.864190", "metadata": { "specversion": { "name": "specversion", @@ -332,9 +332,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareLegRules", - "createdat": "2024-09-14T19:34:18.859990", + "createdat": "2024-09-18T14:18:48.145335", "epoch": 0, - "modifiedat": "2024-09-14T19:34:18.859990", + "modifiedat": "2024-09-18T14:18:48.145335", "metadata": { "specversion": { "name": "specversion", @@ -371,9 +371,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareMedia", - "createdat": "2024-09-14T19:34:22.043899", + "createdat": "2024-09-18T14:18:51.545931", "epoch": 0, - "modifiedat": "2024-09-14T19:34:22.043899", + "modifiedat": "2024-09-18T14:18:51.545931", "metadata": { "specversion": { "name": "specversion", @@ -410,9 +410,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareProducts", - "createdat": "2024-09-14T19:34:25.251924", + "createdat": "2024-09-18T14:18:55.465763", "epoch": 0, - "modifiedat": "2024-09-14T19:34:25.251924", + "modifiedat": "2024-09-18T14:18:55.465763", "metadata": { "specversion": { "name": "specversion", @@ -449,9 +449,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareRules", - "createdat": "2024-09-14T19:34:28.382751", + "createdat": "2024-09-18T14:18:59.022066", "epoch": 0, - "modifiedat": "2024-09-14T19:34:28.382751", + "modifiedat": "2024-09-18T14:18:59.022066", "metadata": { "specversion": { "name": "specversion", @@ -488,9 +488,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FareTransferRules", - "createdat": "2024-09-14T19:34:31.594438", + "createdat": "2024-09-18T14:19:02.517682", "epoch": 0, - "modifiedat": "2024-09-14T19:34:31.594438", + "modifiedat": "2024-09-18T14:19:02.517682", "metadata": { "specversion": { "name": "specversion", @@ -527,9 +527,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.FeedInfo", - "createdat": "2024-09-14T19:34:34.800372", + "createdat": "2024-09-18T14:19:05.869375", "epoch": 0, - "modifiedat": "2024-09-14T19:34:34.800372", + "modifiedat": "2024-09-18T14:19:05.869375", "metadata": { "specversion": { "name": "specversion", @@ -566,9 +566,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Frequencies", - "createdat": "2024-09-14T19:34:37.975904", + "createdat": "2024-09-18T14:19:09.469690", "epoch": 0, - "modifiedat": "2024-09-14T19:34:37.975904", + "modifiedat": "2024-09-18T14:19:09.469690", "metadata": { "specversion": { "name": "specversion", @@ -605,9 +605,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Levels", - "createdat": "2024-09-14T19:34:41.164118", + "createdat": "2024-09-18T14:19:12.723623", "epoch": 0, - "modifiedat": "2024-09-14T19:34:41.164118", + "modifiedat": "2024-09-18T14:19:12.723623", "metadata": { "specversion": { "name": "specversion", @@ -644,9 +644,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.LocationGeoJson", - "createdat": "2024-09-14T19:34:44.385665", + "createdat": "2024-09-18T14:19:16.053215", "epoch": 0, - "modifiedat": "2024-09-14T19:34:44.385665", + "modifiedat": "2024-09-18T14:19:16.053215", "metadata": { "specversion": { "name": "specversion", @@ -683,9 +683,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.LocationGroups", - "createdat": "2024-09-14T19:34:47.584486", + "createdat": "2024-09-18T14:19:19.334478", "epoch": 0, - "modifiedat": "2024-09-14T19:34:47.584486", + "modifiedat": "2024-09-18T14:19:19.334478", "metadata": { "specversion": { "name": "specversion", @@ -722,9 +722,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.LocationGroupStores", - "createdat": "2024-09-14T19:34:50.772270", + "createdat": "2024-09-18T14:19:22.628633", "epoch": 0, - "modifiedat": "2024-09-14T19:34:50.772270", + "modifiedat": "2024-09-18T14:19:22.628633", "metadata": { "specversion": { "name": "specversion", @@ -761,9 +761,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Networks", - "createdat": "2024-09-14T19:34:53.975672", + "createdat": "2024-09-18T14:19:25.926993", "epoch": 0, - "modifiedat": "2024-09-14T19:34:53.975672", + "modifiedat": "2024-09-18T14:19:25.926993", "metadata": { "specversion": { "name": "specversion", @@ -800,9 +800,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Pathways", - "createdat": "2024-09-14T19:34:57.277576", + "createdat": "2024-09-18T14:19:29.178618", "epoch": 0, - "modifiedat": "2024-09-14T19:34:57.277576", + "modifiedat": "2024-09-18T14:19:29.178618", "metadata": { "specversion": { "name": "specversion", @@ -839,9 +839,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.RouteNetworks", - "createdat": "2024-09-14T19:35:00.516165", + "createdat": "2024-09-18T14:19:32.448316", "epoch": 0, - "modifiedat": "2024-09-14T19:35:00.516165", + "modifiedat": "2024-09-18T14:19:32.448316", "metadata": { "specversion": { "name": "specversion", @@ -878,9 +878,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Routes", - "createdat": "2024-09-14T19:35:03.739840", + "createdat": "2024-09-18T14:19:35.714975", "epoch": 0, - "modifiedat": "2024-09-14T19:35:03.739840", + "modifiedat": "2024-09-18T14:19:35.714975", "metadata": { "specversion": { "name": "specversion", @@ -917,9 +917,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Shapes", - "createdat": "2024-09-14T19:35:06.980418", + "createdat": "2024-09-18T14:19:38.989197", "epoch": 0, - "modifiedat": "2024-09-14T19:35:06.980418", + "modifiedat": "2024-09-18T14:19:38.989197", "metadata": { "specversion": { "name": "specversion", @@ -956,9 +956,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.StopAreas", - "createdat": "2024-09-14T19:35:10.194179", + "createdat": "2024-09-18T14:19:42.248833", "epoch": 0, - "modifiedat": "2024-09-14T19:35:10.194179", + "modifiedat": "2024-09-18T14:19:42.248833", "metadata": { "specversion": { "name": "specversion", @@ -995,9 +995,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Stops", - "createdat": "2024-09-14T19:35:13.431326", + "createdat": "2024-09-18T14:19:45.584449", "epoch": 0, - "modifiedat": "2024-09-14T19:35:13.431326", + "modifiedat": "2024-09-18T14:19:45.584449", "metadata": { "specversion": { "name": "specversion", @@ -1034,9 +1034,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.StopTimes", - "createdat": "2024-09-14T19:35:16.641750", + "createdat": "2024-09-18T14:19:48.875701", "epoch": 0, - "modifiedat": "2024-09-14T19:35:16.641750", + "modifiedat": "2024-09-18T14:19:48.875701", "metadata": { "specversion": { "name": "specversion", @@ -1073,9 +1073,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Timeframes", - "createdat": "2024-09-14T19:35:19.852768", + "createdat": "2024-09-18T14:19:52.121539", "epoch": 0, - "modifiedat": "2024-09-14T19:35:19.852768", + "modifiedat": "2024-09-18T14:19:52.121539", "metadata": { "specversion": { "name": "specversion", @@ -1112,9 +1112,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Transfers", - "createdat": "2024-09-14T19:35:23.095140", + "createdat": "2024-09-18T14:19:55.364061", "epoch": 0, - "modifiedat": "2024-09-14T19:35:23.095140", + "modifiedat": "2024-09-18T14:19:55.364061", "metadata": { "specversion": { "name": "specversion", @@ -1151,9 +1151,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Translations", - "createdat": "2024-09-14T19:35:26.333256", + "createdat": "2024-09-18T14:19:58.582820", "epoch": 0, - "modifiedat": "2024-09-14T19:35:26.333256", + "modifiedat": "2024-09-18T14:19:58.582820", "metadata": { "specversion": { "name": "specversion", @@ -1190,9 +1190,9 @@ "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/GeneralTransitFeedStatic/schemas/GeneralTransitFeedStatic.Trips", - "createdat": "2024-09-14T19:35:29.580497", + "createdat": "2024-09-18T14:20:01.902281", "epoch": 0, - "modifiedat": "2024-09-14T19:35:29.580497", + "modifiedat": "2024-09-18T14:20:01.902281", "metadata": { "specversion": { "name": "specversion", @@ -1224,9 +1224,9 @@ } } }, - "createdat": "2024-09-14T19:34:02.940936", + "createdat": "2024-09-18T14:18:31.832628", "epoch": 0, - "modifiedat": "2024-09-14T19:34:02.940936" + "modifiedat": "2024-09-18T14:18:31.832628" } }, "schemagroups": { @@ -1517,9 +1517,9 @@ ], "doc": "Realtime positioning information for a given vehicle." }, - "createdat": "2024-09-14T19:33:52.493022", + "createdat": "2024-09-18T14:18:21.380862", "epoch": 0, - "modifiedat": "2024-09-14T19:33:52.493022" + "modifiedat": "2024-09-18T14:18:21.380862" } } }, @@ -1767,9 +1767,9 @@ ], "doc": "Entities used in the feed. Realtime update of the progress of a vehicle along a trip. Depending on the value of ScheduleRelationship, a TripUpdate can specify: - A trip that proceeds along the schedule. - A trip that proceeds along a route but has no fixed schedule. - A trip that have been added or removed with regard to schedule. The updates can be for future, predicted arrival/departure events, or for past events that already occurred. Normally, updates should get more precise and more certain (see uncertainty below) as the events gets closer to current time. Even if that is not possible, the information for past events should be precise and certain. In particular, if an update points to time in the past but its update's uncertainty is not 0, the client should conclude that the update is a (wrong) prediction and that the trip has not completed yet. Note that the update can describe a trip that is already completed. To this end, it is enough to provide an update for the last stop of the trip. If the time of that is in the past, the client will conclude from that that the whole trip is in the past (it is possible, although inconsequential, to also provide updates for preceding stops). This option is most relevant for a trip that has completed ahead of schedule, but according to the schedule, the trip is still proceeding at the current time. Removing the updates for this trip could make the client assume that the trip is still proceeding. Note that the feed provider is allowed, but not required, to purge past updates - this is one case where this would be practically useful." }, - "createdat": "2024-09-14T19:33:55.674913", + "createdat": "2024-09-18T14:18:24.599797", "epoch": 0, - "modifiedat": "2024-09-14T19:33:55.674913" + "modifiedat": "2024-09-18T14:18:24.599797" } } }, @@ -2074,16 +2074,16 @@ ], "doc": "An alert, indicating some sort of incident in the public transit network." }, - "createdat": "2024-09-14T19:33:58.921048", + "createdat": "2024-09-18T14:18:27.781447", "epoch": 0, - "modifiedat": "2024-09-14T19:33:58.921048" + "modifiedat": "2024-09-18T14:18:27.781447" } } } }, - "createdat": "2024-09-14T19:33:52.491002", + "createdat": "2024-09-18T14:18:21.378335", "epoch": 0, - "modifiedat": "2024-09-14T19:33:52.491002" + "modifiedat": "2024-09-18T14:18:21.378335" }, "GeneralTransitFeedStatic": { "id": "GeneralTransitFeedStatic", @@ -2159,9 +2159,9 @@ } ] }, - "createdat": "2024-09-14T19:34:02.166799", + "createdat": "2024-09-18T14:18:31.020958", "epoch": 0, - "modifiedat": "2024-09-14T19:34:02.166799" + "modifiedat": "2024-09-18T14:18:31.020958" } } }, @@ -2208,9 +2208,9 @@ } ] }, - "createdat": "2024-09-14T19:34:05.329844", + "createdat": "2024-09-18T14:18:34.277303", "epoch": 0, - "modifiedat": "2024-09-14T19:34:05.329844" + "modifiedat": "2024-09-18T14:18:34.277303" } } }, @@ -2324,9 +2324,9 @@ } ] }, - "createdat": "2024-09-14T19:34:08.516068", + "createdat": "2024-09-18T14:18:37.506571", "epoch": 0, - "modifiedat": "2024-09-14T19:34:08.516068" + "modifiedat": "2024-09-18T14:18:37.506571" } } }, @@ -2373,9 +2373,9 @@ } ] }, - "createdat": "2024-09-14T19:34:11.689538", + "createdat": "2024-09-18T14:18:40.761099", "epoch": 0, - "modifiedat": "2024-09-14T19:34:11.689538" + "modifiedat": "2024-09-18T14:18:40.761099" } } }, @@ -2441,9 +2441,9 @@ } ] }, - "createdat": "2024-09-14T19:34:14.878250", + "createdat": "2024-09-18T14:18:44.049950", "epoch": 0, - "modifiedat": "2024-09-14T19:34:14.878250" + "modifiedat": "2024-09-18T14:18:44.049950" } } }, @@ -2508,9 +2508,9 @@ } ] }, - "createdat": "2024-09-14T19:34:18.076686", + "createdat": "2024-09-18T14:18:47.317174", "epoch": 0, - "modifiedat": "2024-09-14T19:34:18.076686" + "modifiedat": "2024-09-18T14:18:47.317174" } } }, @@ -2557,9 +2557,9 @@ } ] }, - "createdat": "2024-09-14T19:34:21.248903", + "createdat": "2024-09-18T14:18:50.603874", "epoch": 0, - "modifiedat": "2024-09-14T19:34:21.248903" + "modifiedat": "2024-09-18T14:18:50.603874" } } }, @@ -2606,9 +2606,9 @@ } ] }, - "createdat": "2024-09-14T19:34:24.455162", + "createdat": "2024-09-18T14:18:54.598494", "epoch": 0, - "modifiedat": "2024-09-14T19:34:24.455162" + "modifiedat": "2024-09-18T14:18:54.598494" } } }, @@ -2668,9 +2668,9 @@ } ] }, - "createdat": "2024-09-14T19:34:27.606118", + "createdat": "2024-09-18T14:18:58.126714", "epoch": 0, - "modifiedat": "2024-09-14T19:34:27.606118" + "modifiedat": "2024-09-18T14:18:58.126714" } } }, @@ -2744,9 +2744,9 @@ } ] }, - "createdat": "2024-09-14T19:34:30.797725", + "createdat": "2024-09-18T14:19:01.555072", "epoch": 0, - "modifiedat": "2024-09-14T19:34:30.797725" + "modifiedat": "2024-09-18T14:19:01.555072" } } }, @@ -2834,9 +2834,9 @@ } ] }, - "createdat": "2024-09-14T19:34:33.988340", + "createdat": "2024-09-18T14:19:05.035722", "epoch": 0, - "modifiedat": "2024-09-14T19:34:33.988340" + "modifiedat": "2024-09-18T14:19:05.035722" } } }, @@ -2884,9 +2884,9 @@ } ] }, - "createdat": "2024-09-14T19:34:37.180477", + "createdat": "2024-09-18T14:19:08.491070", "epoch": 0, - "modifiedat": "2024-09-14T19:34:37.180477" + "modifiedat": "2024-09-18T14:19:08.491070" } } }, @@ -2924,9 +2924,9 @@ } ] }, - "createdat": "2024-09-14T19:34:40.400248", + "createdat": "2024-09-18T14:19:11.941969", "epoch": 0, - "modifiedat": "2024-09-14T19:34:40.400248" + "modifiedat": "2024-09-18T14:19:11.941969" } } }, @@ -2960,9 +2960,9 @@ } ] }, - "createdat": "2024-09-14T19:34:43.596618", + "createdat": "2024-09-18T14:19:15.260010", "epoch": 0, - "modifiedat": "2024-09-14T19:34:43.596618" + "modifiedat": "2024-09-18T14:19:15.260010" } } }, @@ -3009,9 +3009,9 @@ } ] }, - "createdat": "2024-09-14T19:34:46.768025", + "createdat": "2024-09-18T14:19:18.502157", "epoch": 0, - "modifiedat": "2024-09-14T19:34:46.768025" + "modifiedat": "2024-09-18T14:19:18.502157" } } }, @@ -3045,9 +3045,9 @@ } ] }, - "createdat": "2024-09-14T19:34:49.978137", + "createdat": "2024-09-18T14:19:21.813559", "epoch": 0, - "modifiedat": "2024-09-14T19:34:49.978137" + "modifiedat": "2024-09-18T14:19:21.813559" } } }, @@ -3094,9 +3094,9 @@ } ] }, - "createdat": "2024-09-14T19:34:53.196657", + "createdat": "2024-09-18T14:19:25.164529", "epoch": 0, - "modifiedat": "2024-09-14T19:34:53.196657" + "modifiedat": "2024-09-18T14:19:25.164529" } } }, @@ -3203,9 +3203,9 @@ } ] }, - "createdat": "2024-09-14T19:34:56.449561", + "createdat": "2024-09-18T14:19:28.405668", "epoch": 0, - "modifiedat": "2024-09-14T19:34:56.449561" + "modifiedat": "2024-09-18T14:19:28.405668" } } }, @@ -3239,9 +3239,9 @@ } ] }, - "createdat": "2024-09-14T19:34:59.706992", + "createdat": "2024-09-18T14:19:31.633477", "epoch": 0, - "modifiedat": "2024-09-14T19:34:59.706992" + "modifiedat": "2024-09-18T14:19:31.633477" } } }, @@ -3404,9 +3404,9 @@ } ] }, - "createdat": "2024-09-14T19:35:02.942869", + "createdat": "2024-09-18T14:19:34.900235", "epoch": 0, - "modifiedat": "2024-09-14T19:35:02.942869" + "modifiedat": "2024-09-18T14:19:34.900235" } } }, @@ -3454,9 +3454,9 @@ } ] }, - "createdat": "2024-09-14T19:35:06.146186", + "createdat": "2024-09-18T14:19:38.176677", "epoch": 0, - "modifiedat": "2024-09-14T19:35:06.146186" + "modifiedat": "2024-09-18T14:19:38.176677" } } }, @@ -3490,9 +3490,9 @@ } ] }, - "createdat": "2024-09-14T19:35:09.421924", + "createdat": "2024-09-18T14:19:41.443410", "epoch": 0, - "modifiedat": "2024-09-14T19:35:09.421924" + "modifiedat": "2024-09-18T14:19:41.443410" } } }, @@ -3656,9 +3656,9 @@ } ] }, - "createdat": "2024-09-14T19:35:12.622154", + "createdat": "2024-09-18T14:19:44.774269", "epoch": 0, - "modifiedat": "2024-09-14T19:35:12.622154" + "modifiedat": "2024-09-18T14:19:44.774269" } } }, @@ -3818,9 +3818,9 @@ } ] }, - "createdat": "2024-09-14T19:35:15.838889", + "createdat": "2024-09-18T14:19:48.066988", "epoch": 0, - "modifiedat": "2024-09-14T19:35:15.838889" + "modifiedat": "2024-09-18T14:19:48.066988" } } }, @@ -3963,9 +3963,9 @@ } ] }, - "createdat": "2024-09-14T19:35:19.055283", + "createdat": "2024-09-18T14:19:51.301593", "epoch": 0, - "modifiedat": "2024-09-14T19:35:19.055283" + "modifiedat": "2024-09-18T14:19:51.301593" } } }, @@ -4008,9 +4008,9 @@ } ] }, - "createdat": "2024-09-14T19:35:22.302685", + "createdat": "2024-09-18T14:19:54.552806", "epoch": 0, - "modifiedat": "2024-09-14T19:35:22.302685" + "modifiedat": "2024-09-18T14:19:54.552806" } } }, @@ -4049,9 +4049,9 @@ } ] }, - "createdat": "2024-09-14T19:35:25.528325", + "createdat": "2024-09-18T14:19:57.817607", "epoch": 0, - "modifiedat": "2024-09-14T19:35:25.528325" + "modifiedat": "2024-09-18T14:19:57.817607" } } }, @@ -4265,16 +4265,16 @@ } ] }, - "createdat": "2024-09-14T19:35:28.764187", + "createdat": "2024-09-18T14:20:01.085696", "epoch": 0, - "modifiedat": "2024-09-14T19:35:28.764187" + "modifiedat": "2024-09-18T14:20:01.085696" } } } }, - "createdat": "2024-09-14T19:34:02.155037", + "createdat": "2024-09-18T14:18:31.008958", "epoch": 0, - "modifiedat": "2024-09-14T19:34:02.155037" + "modifiedat": "2024-09-18T14:18:31.008958" } } } \ No newline at end of file diff --git a/noaa/CONTAINER.md b/noaa/CONTAINER.md index 56ad4d4..8e8129c 100644 --- a/noaa/CONTAINER.md +++ b/noaa/CONTAINER.md @@ -10,6 +10,12 @@ The National Oceanic and Atmospheric Administration (NOAA) Tides and Currents AP The bridge retrieves data from the NOAA Tides and Currents API and writes it to a Kafka topic as [CloudEvents](https://cloudevents.io/) in a JSON format, which is documented in [EVENTS.md](EVENTS.md). +## Database Schemas and handling + +If you want to build a full data pipeline with all events ingested into +database, the integration with Fabric Eventhouse and Azure Data Explorer is +described in [DATABASE.md](../DATABASE.md). + ## Installing the Container Image Pull the container image from the GitHub Container Registry: diff --git a/noaa/noaa/noaa.kql b/noaa/kql/noaa.kql similarity index 100% rename from noaa/noaa/noaa.kql rename to noaa/kql/noaa.kql diff --git a/noaa/kql/noaa.kql.md b/noaa/kql/noaa.kql.md new file mode 100644 index 0000000..7c4e2e7 --- /dev/null +++ b/noaa/kql/noaa.kql.md @@ -0,0 +1,2 @@ +# noaa/kql/noaa.kql + diff --git a/gtfs/xreg/run-kql-script.ps1 b/noaa/kql/run-kql-script.ps1 similarity index 100% rename from gtfs/xreg/run-kql-script.ps1 rename to noaa/kql/run-kql-script.ps1 diff --git a/noaa/noaa/run-kql-script.ps1 b/noaa/noaa/run-kql-script.ps1 deleted file mode 100644 index 79b4ab7..0000000 --- a/noaa/noaa/run-kql-script.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -param( - [Parameter(Mandatory=$true)] - [string]$clusterUri, - - [Parameter(Mandatory=$true)] - [string]$database, - - [Parameter(Mandatory=$true)] - [string]$script -) - -# Check if kusto.cli is in the path -if (-not (Get-Command -Name "kusto.cli" -ErrorAction SilentlyContinue)) { - # Create a temporary directory - $tempDir = New-Item -ItemType Directory -Path $env:TEMP -Name "kusto_cli_temp" -ErrorAction Stop - - try { - # Download the kusto.cli zip file - $zipFile = Join-Path -Path $tempDir.FullName -ChildPath "kusto_cli.zip" - Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.Azure.Kusto.Tools" -OutFile $zipFile -ErrorAction Stop - - # Extract the zip file - Expand-Archive -Path $zipFile -DestinationPath $tempDir.FullName -Force -ErrorAction Stop - - # Run kusto.cli from the tools directory - $toolsDir = Join-Path -Path $tempDir.FullName -ChildPath "tools" - $kustoCliPath = Join-Path -Path $toolsDir -ChildPath "kusto.cli" - & $kustoCliPath "${clusterUri}/${database};fed=true" -script:${script} -linemode:false -keeprunning:false - } - finally { - # Clean up the temporary directory - Remove-Item -Path $tempDir.FullName -Recurse -Force -ErrorAction SilentlyContinue - } -} -else { - # kusto.cli is already in the path, so run it directly - & kusto.cli "${clusterUri}/${database};fed=true" -script:${script} -linemode:false -keeprunning:false -} diff --git a/noaa/noaa/noaa.avsc b/noaa/xreg/noaa.avsc similarity index 100% rename from noaa/noaa/noaa.avsc rename to noaa/xreg/noaa.avsc diff --git a/noaa/noaa/noaa.xreg.json b/noaa/xreg/noaa.xreg.json similarity index 100% rename from noaa/noaa/noaa.xreg.json rename to noaa/xreg/noaa.xreg.json diff --git a/pegelonline/CONTAINER.md b/pegelonline/CONTAINER.md index 32cda96..1215d2c 100644 --- a/pegelonline/CONTAINER.md +++ b/pegelonline/CONTAINER.md @@ -21,6 +21,12 @@ in a JSON format documented in [EVENTS.md](EVENTS.md). You can configure the bridge to handle multiple stations by supplying their identifiers in the configuration. +## Database Schemas and handling + +If you want to build a full data pipeline with all events ingested into +database, the integration with Fabric Eventhouse and Azure Data Explorer is +described in [DATABASE.md](../DATABASE.md). + ## Installing the Container Image Pull the container image from the GitHub Container Registry: diff --git a/pegelonline/kql/create-kql-script.ps1 b/pegelonline/kql/create-kql-script.ps1 new file mode 100644 index 0000000..d7c963a --- /dev/null +++ b/pegelonline/kql/create-kql-script.ps1 @@ -0,0 +1,13 @@ +$scriptPath = Split-Path -Parent $PSCommandPath +$jsonFiles = Get-ChildItem -Path "$scriptPath/../xreg" -Filter "*.avsc" | Select-Object -ExpandProperty FullName +$outputFile = ".schemas.avsc" + +$mergedArray = @() +foreach ($file in $jsonFiles) { + $jsonContent = Get-Content $file -Raw | ConvertFrom-Json + $mergedArray += $jsonContent +} +$mergedArray | ConvertTo-Json -Depth 20 | Out-File $outputFile -Encoding UTF8 + +avrotize a2k $outputFile --emit-cloudevents-dispatch --emit-cloudevents-columns > pegelonline.kql +Remove-Item $outputFile \ No newline at end of file diff --git a/pegelonline/xreg/pegelonline.kql b/pegelonline/kql/pegelonline.kql similarity index 98% rename from pegelonline/xreg/pegelonline.kql rename to pegelonline/kql/pegelonline.kql index 7c0567d..12f7cc7 100644 --- a/pegelonline/xreg/pegelonline.kql +++ b/pegelonline/kql/pegelonline.kql @@ -87,6 +87,8 @@ ``` +.drop materialized-view CurrentMeasurementLatest ifexists; + .create materialized-view with (backfill=true) CurrentMeasurementLatest on table CurrentMeasurement { CurrentMeasurement | summarize arg_max(___time, *) by ___type, ___source, ___subject } @@ -179,6 +181,8 @@ ``` +.drop materialized-view StationLatest ifexists; + .create materialized-view with (backfill=true) StationLatest on table Station { Station | summarize arg_max(___time, *) by ___type, ___source, ___subject } diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/pyproject.toml b/pegelonline/pegelonline_producer/pegelonline_producer_data/pyproject.toml index 8b7a3cc..6aedfe0 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/pyproject.toml +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/pyproject.toml @@ -2,7 +2,7 @@ name = "pegelonline-producer-data" version = "0.1.0" description = "A package for handling Avro schema data" -authors = ["Clemens Vasters"] +authors = ["Your Name"] license = "MIT" packages = [ { include = "pegelonline_producer_data", from="src" } ] diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/currentmeasurement.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/currentmeasurement.py index 64d96f6..321926e 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/currentmeasurement.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/currentmeasurement.py @@ -26,7 +26,7 @@ class CurrentMeasurement: timestamp: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="timestamp")) value: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="value")) stateMnwMhw: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stateMnwMhw")) - stateNswHsw: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stateNswHsw")) + stateNswHsw: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="stateNswHsw")) def __post_init__(self): @@ -89,7 +89,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/station.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/station.py index 69a325f..54baacf 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/station.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/station.py @@ -35,7 +35,7 @@ class Station: agency: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="agency")) longitude: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="longitude")) latitude: float=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="latitude")) - water: Water=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="water")) + water: Water=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="water")) def __post_init__(self): @@ -103,7 +103,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/water.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/water.py index 8739ca8..608708f 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/water.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/src/pegelonline_producer_data/de/wsv/pegelonline/water.py @@ -20,7 +20,7 @@ class Water: longname (str): Full name of the water body (maximum 255 characters).""" shortname: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="shortname")) - longname: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="longname")) + longname: str=dataclasses.field(kw_only=True, metadata=dataclasses_json.config(field_name="longname")) def __post_init__(self): @@ -80,7 +80,9 @@ def to_byte_array(self, content_type_string: str) -> bytes: content_type = content_type_string.split(';')[0].strip() result = None if content_type == 'application/json': + #pylint: disable=no-member result = self.to_json() + #pylint: enable=no-member if result is not None and content_type.endswith('+gzip'): with io.BytesIO() as stream: diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_currentmeasurement.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_currentmeasurement.py index 2f55dfa..b89ade0 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_currentmeasurement.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_currentmeasurement.py @@ -10,6 +10,7 @@ from pegelonline_producer_data.de.wsv.pegelonline.currentmeasurement import CurrentMeasurement + class Test_CurrentMeasurement(unittest.TestCase): """ Test case for CurrentMeasurement @@ -27,11 +28,11 @@ def create_instance(): Create instance of CurrentMeasurement for testing """ instance = CurrentMeasurement( - station_uuid='gsffydwifedxfpaopebq', - timestamp='xmhsqrgkqrqwpvixvgbb', - value=float(6.312102505425477), - stateMnwMhw='scspspytmyexajpyvddy', - stateNswHsw='ijbusiwibplvnhrqjbfx' + station_uuid='bwalxghvlecmmqijrlja', + timestamp='egjchkvyalqznscstcyw', + value=float(99.04357651670534), + stateMnwMhw='mucujvicuwiwizvybvoa', + stateNswHsw='uaykmvloeexwaucoijoz' ) return instance @@ -40,7 +41,7 @@ def test_station_uuid_property(self): """ Test station_uuid property """ - test_value = 'gsffydwifedxfpaopebq' + test_value = 'bwalxghvlecmmqijrlja' self.instance.station_uuid = test_value self.assertEqual(self.instance.station_uuid, test_value) @@ -48,7 +49,7 @@ def test_timestamp_property(self): """ Test timestamp property """ - test_value = 'xmhsqrgkqrqwpvixvgbb' + test_value = 'egjchkvyalqznscstcyw' self.instance.timestamp = test_value self.assertEqual(self.instance.timestamp, test_value) @@ -56,7 +57,7 @@ def test_value_property(self): """ Test value property """ - test_value = float(6.312102505425477) + test_value = float(99.04357651670534) self.instance.value = test_value self.assertEqual(self.instance.value, test_value) @@ -64,7 +65,7 @@ def test_stateMnwMhw_property(self): """ Test stateMnwMhw property """ - test_value = 'scspspytmyexajpyvddy' + test_value = 'mucujvicuwiwizvybvoa' self.instance.stateMnwMhw = test_value self.assertEqual(self.instance.stateMnwMhw, test_value) @@ -72,7 +73,7 @@ def test_stateNswHsw_property(self): """ Test stateNswHsw property """ - test_value = 'ijbusiwibplvnhrqjbfx' + test_value = 'uaykmvloeexwaucoijoz' self.instance.stateNswHsw = test_value self.assertEqual(self.instance.stateNswHsw, test_value) diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_station.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_station.py index 5f8b886..36c3bfd 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_station.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_station.py @@ -11,6 +11,7 @@ from pegelonline_producer_data.de.wsv.pegelonline.station import Station from test_pegelonline_producer_data_de_wsv_pegelonline_water import Test_Water + class Test_Station(unittest.TestCase): """ Test case for Station @@ -28,14 +29,14 @@ def create_instance(): Create instance of Station for testing """ instance = Station( - uuid='dndwfdvhvhoaojulmqgy', - number='opexliaohznjiyllpinj', - shortname='oivbxhufrhkpzaagltqy', - longname='xgfgpogecrlqeatwdndl', - km=float(32.02403314849423), - agency='ymzrvqlmhluvwxwqcymg', - longitude=float(40.99463405832166), - latitude=float(80.06704490885124), + uuid='ygciorrlaoltnvqlkqog', + number='aqiqdzfgqbgivqgnrfhs', + shortname='yoqkvmwiherlqorzygqq', + longname='vkdwfqyyytjjpnkrrfiv', + km=float(8.379605816258096), + agency='zcaurpgpxmmtzjjjxzpi', + longitude=float(75.01678132618342), + latitude=float(0.051411525612299336), water=Test_Water.create_instance() ) return instance @@ -45,7 +46,7 @@ def test_uuid_property(self): """ Test uuid property """ - test_value = 'dndwfdvhvhoaojulmqgy' + test_value = 'ygciorrlaoltnvqlkqog' self.instance.uuid = test_value self.assertEqual(self.instance.uuid, test_value) @@ -53,7 +54,7 @@ def test_number_property(self): """ Test number property """ - test_value = 'opexliaohznjiyllpinj' + test_value = 'aqiqdzfgqbgivqgnrfhs' self.instance.number = test_value self.assertEqual(self.instance.number, test_value) @@ -61,7 +62,7 @@ def test_shortname_property(self): """ Test shortname property """ - test_value = 'oivbxhufrhkpzaagltqy' + test_value = 'yoqkvmwiherlqorzygqq' self.instance.shortname = test_value self.assertEqual(self.instance.shortname, test_value) @@ -69,7 +70,7 @@ def test_longname_property(self): """ Test longname property """ - test_value = 'xgfgpogecrlqeatwdndl' + test_value = 'vkdwfqyyytjjpnkrrfiv' self.instance.longname = test_value self.assertEqual(self.instance.longname, test_value) @@ -77,7 +78,7 @@ def test_km_property(self): """ Test km property """ - test_value = float(32.02403314849423) + test_value = float(8.379605816258096) self.instance.km = test_value self.assertEqual(self.instance.km, test_value) @@ -85,7 +86,7 @@ def test_agency_property(self): """ Test agency property """ - test_value = 'ymzrvqlmhluvwxwqcymg' + test_value = 'zcaurpgpxmmtzjjjxzpi' self.instance.agency = test_value self.assertEqual(self.instance.agency, test_value) @@ -93,7 +94,7 @@ def test_longitude_property(self): """ Test longitude property """ - test_value = float(40.99463405832166) + test_value = float(75.01678132618342) self.instance.longitude = test_value self.assertEqual(self.instance.longitude, test_value) @@ -101,7 +102,7 @@ def test_latitude_property(self): """ Test latitude property """ - test_value = float(80.06704490885124) + test_value = float(0.051411525612299336) self.instance.latitude = test_value self.assertEqual(self.instance.latitude, test_value) diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_water.py b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_water.py index 222f4f2..00e0e75 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_water.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_data/tests/test_pegelonline_producer_data_de_wsv_pegelonline_water.py @@ -10,6 +10,7 @@ from pegelonline_producer_data.de.wsv.pegelonline.water import Water + class Test_Water(unittest.TestCase): """ Test case for Water @@ -27,8 +28,8 @@ def create_instance(): Create instance of Water for testing """ instance = Water( - shortname='nsuwwpjcxzslkxpnyffk', - longname='zpmjrthehltzjkjjgybf' + shortname='uqypljtnvpnnjkfqwhlw', + longname='epfbzebxvmqavbchvxpt' ) return instance @@ -37,7 +38,7 @@ def test_shortname_property(self): """ Test shortname property """ - test_value = 'nsuwwpjcxzslkxpnyffk' + test_value = 'uqypljtnvpnnjkfqwhlw' self.instance.shortname = test_value self.assertEqual(self.instance.shortname, test_value) @@ -45,7 +46,7 @@ def test_longname_property(self): """ Test longname property """ - test_value = 'zpmjrthehltzjkjjgybf' + test_value = 'epfbzebxvmqavbchvxpt' self.instance.longname = test_value self.assertEqual(self.instance.longname, test_value) diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/pyproject.toml b/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/pyproject.toml index 3cfc635..f8a9646 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/pyproject.toml +++ b/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "pegelonline-producer-kafka-producer" description = "pegelonline_producer_kafka_producer Apache Kafka consumer library" -authors = ["Clemens Vasters "] +authors = ["Your Name "] readme = "README.md" version = "0.1.0" # Placeholder version, dynamic versioning can be handled with plugins packages = [{include = "pegelonline_producer_kafka_producer", from = "src"}] diff --git a/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/src/pegelonline_producer_kafka_producer/producer.py b/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/src/pegelonline_producer_kafka_producer/producer.py index b329c38..aeab02c 100644 --- a/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/src/pegelonline_producer_kafka_producer/producer.py +++ b/pegelonline/pegelonline_producer/pegelonline_producer_kafka_producer/src/pegelonline_producer_kafka_producer/producer.py @@ -60,7 +60,7 @@ async def send_de_wsv_pegelonline_station(self,_feedurl : str, _station_id : str attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -70,55 +70,6 @@ async def send_de_wsv_pegelonline_station(self,_feedurl : str, _station_id : str if flush_producer: self.producer.flush() - @classmethod - def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: - """ - Parse the connection string and extract bootstrap server, topic name, username, and password. - - Args: - connection_string (str): The connection string. - - Returns: - Tuple[Dict[str, str], str]: Kafka config, topic name - """ - config_dict = { - 'security.protocol': 'SASL_SSL', - 'sasl.mechanisms': 'PLAIN', - 'sasl.username': '$ConnectionString', - 'sasl.password': connection_string.strip() - } - kafka_topic = None - try: - for part in connection_string.split(';'): - if 'Endpoint' in part: - config_dict['bootstrap.servers'] = part.split('=')[1].strip( - '"').replace('sb://', '').replace('/', '')+':9093' - elif 'EntityPath' in part: - kafka_topic = part.split('=')[1].strip('"') - except IndexError as e: - raise ValueError("Invalid connection string format") from e - return config_dict, kafka_topic - - @classmethod - def from_connection_string(cls, connection_string: str, topic: typing.Optional[str]=None, content_mode: typing.Literal['structured','binary']='structured') -> 'DeWsvPegelonlineEventProducer': - """ - Create a Kafka producer from a connection string and a topic name. - - Args: - connection_string (str): The connection string. - topic (Optional[str]): The Kafka topic. - content_mode (typing.Literal['structured','binary']): The content mode to use for sending events - - Returns: - Producer: The Kafka producer - """ - config, topic_name = cls.parse_connection_string(connection_string) - if topic: - topic_name = topic - if not topic_name: - raise ValueError("Topic name not found in connection string") - return cls(Producer(config), topic_name, content_mode) - async def send_de_wsv_pegelonline_current_measurement(self,_feedurl : str, _station_id : str, data: CurrentMeasurement, content_type: str = "application/json", flush_producer=True, key_mapper: typing.Callable[[CloudEvent, CurrentMeasurement], str]=None) -> None: """ @@ -142,7 +93,7 @@ async def send_de_wsv_pegelonline_current_measurement(self,_feedurl : str, _stat attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" @@ -152,6 +103,7 @@ async def send_de_wsv_pegelonline_current_measurement(self,_feedurl : str, _stat if flush_producer: self.producer.flush() + @classmethod def parse_connection_string(cls, connection_string: str) -> typing.Tuple[typing.Dict[str, str], str]: """ diff --git a/pegelonline/xreg/create-kql-script.ps1 b/pegelonline/xreg/create-kql-script.ps1 deleted file mode 100644 index 5134101..0000000 --- a/pegelonline/xreg/create-kql-script.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -$jsonFiles = @("currentmeasurement.avsc", "station.avsc") -$outputFile = "schemas.avsc" - -$mergedArray = @() -foreach ($file in $jsonFiles) { - $jsonContent = Get-Content $file -Raw | ConvertFrom-Json - $mergedArray += $jsonContent -} -$mergedArray | ConvertTo-Json -Depth 10 | Out-File $outputFile -Encoding UTF8 - -avrotize a2k schemas.avsc --emit-cloudevents-dispatch --emit-cloudevents-columns > pegelonline.kql diff --git a/pegelonline/xreg/pegelonline.xreg.json b/pegelonline/xreg/pegelonline.xreg.json index 0b6cf48..c2a9f46 100644 --- a/pegelonline/xreg/pegelonline.xreg.json +++ b/pegelonline/xreg/pegelonline.xreg.json @@ -8,14 +8,13 @@ "messages": { "de.wsv.pegelonline.Station": { "id": "de.wsv.pegelonline.Station", - "description": "A PEGELONLINE station with location and water body information.", "format": "CloudEvents/1.0", "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/de.wsv.pegelonline/schemas/de.wsv.pegelonline.Station", - "createdat": "2024-09-10T15:02:55.573631", + "createdat": "2024-09-18T14:22:31.895724", "epoch": 0, - "modifiedat": "2024-09-10T15:02:55.573631", + "modifiedat": "2024-09-18T14:22:31.895724", "metadata": { "specversion": { "name": "specversion", @@ -48,14 +47,13 @@ }, "de.wsv.pegelonline.CurrentMeasurement": { "id": "de.wsv.pegelonline.CurrentMeasurement", - "description": "The current measurement for a PEGELONLINE station.", "format": "CloudEvents/1.0", "binding": "None", "schemaformat": "Avro", "schemaurl": "#/schemagroups/de.wsv.pegelonline/schemas/de.wsv.pegelonline.CurrentMeasurement", - "createdat": "2024-09-10T15:02:58.776148", + "createdat": "2024-09-18T14:22:35.100298", "epoch": 0, - "modifiedat": "2024-09-10T15:02:58.776148", + "modifiedat": "2024-09-18T14:22:35.100298", "metadata": { "specversion": { "name": "specversion", @@ -87,9 +85,9 @@ } } }, - "createdat": "2024-09-10T15:02:55.572645", + "createdat": "2024-09-18T14:22:31.895724", "epoch": 0, - "modifiedat": "2024-09-10T15:02:55.572645" + "modifiedat": "2024-09-18T14:22:31.895724" } }, "schemagroups": { @@ -171,9 +169,9 @@ } ] }, - "createdat": "2024-09-10T15:02:54.786444", + "createdat": "2024-09-18T14:22:31.131859", "epoch": 0, - "modifiedat": "2024-09-10T15:02:54.786444" + "modifiedat": "2024-09-18T14:22:31.131859" } } }, @@ -221,16 +219,16 @@ } ] }, - "createdat": "2024-09-10T15:02:57.965791", + "createdat": "2024-09-18T14:22:34.289227", "epoch": 0, - "modifiedat": "2024-09-10T15:02:57.965791" + "modifiedat": "2024-09-18T14:22:34.289227" } } } }, - "createdat": "2024-09-10T15:02:54.777478", + "createdat": "2024-09-18T14:22:31.116771", "epoch": 0, - "modifiedat": "2024-09-10T15:02:54.777478" + "modifiedat": "2024-09-18T14:22:31.116771" } } } \ No newline at end of file diff --git a/pegelonline/xreg/schemas.avsc b/pegelonline/xreg/schemas.avsc deleted file mode 100644 index a9b7ba0..0000000 --- a/pegelonline/xreg/schemas.avsc +++ /dev/null @@ -1,107 +0,0 @@ -[ - { - "type": "record", - "name": "CurrentMeasurement", - "namespace": "de.wsv.pegelonline", - "doc": "Schema representing the current measurement for a PEGELONLINE station.", - "fields": [ - { - "name": "station_uuid", - "type": "string", - "doc": "Unique immutable identifier of the station." - }, - { - "name": "timestamp", - "type": "string", - "doc": "Timestamp of the current measurement encoded in ISO_8601 format." - }, - { - "name": "value", - "type": "double", - "doc": "Current measured value as a decimal number in the unit defined by the station's timeseries." - }, - { - "name": "stateMnwMhw", - "type": { - "type": "string", - "doc": "State of the current water level compared to mean low water (MNW) and mean high water (MHW). Possible values: 'low', 'normal', 'high', 'unknown', 'commented', 'out-dated'." - } - }, - { - "name": "stateNswHsw", - "type": { - "type": "string", - "doc": "State of the current water level compared to the highest navigable water level (HSW). Possible values: 'normal', 'high', 'unknown', 'commented', 'out-dated'." - } - } - ] - }, - { - "type": "record", - "name": "Station", - "namespace": "de.wsv.pegelonline", - "doc": "Schema representing a PEGELONLINE station with location and water body information.", - "fields": [ - { - "name": "uuid", - "type": "string", - "doc": "Unique immutable identifier of the station." - }, - { - "name": "number", - "type": "string", - "doc": "Station number representing the unique code of the station." - }, - { - "name": "shortname", - "type": "string", - "doc": "Short name of the station (maximum 40 characters)." - }, - { - "name": "longname", - "type": "string", - "doc": "Full name of the station (maximum 255 characters)." - }, - { - "name": "km", - "type": "double", - "doc": "River kilometer marking of the station location." - }, - { - "name": "agency", - "type": "string", - "doc": "Waterways and Shipping Office responsible for the station." - }, - { - "name": "longitude", - "type": "double", - "doc": "Longitude coordinate of the station in WGS84 decimal notation." - }, - { - "name": "latitude", - "type": "double", - "doc": "Latitude coordinate of the station in WGS84 decimal notation." - }, - { - "name": "water", - "type": { - "type": "record", - "name": "Water", - "doc": "Details of the water body associated with the station.", - "fields": [ - { - "name": "shortname", - "type": "string", - "doc": "Short name of the water body (maximum 40 characters)." - }, - { - "name": "longname", - "type": "string", - "doc": "Full name of the water body (maximum 255 characters)." - } - ] - } - } - ] - } -] diff --git a/rss/CONTAINER.md b/rss/CONTAINER.md index 8bc5efe..2c03e0e 100644 --- a/rss/CONTAINER.md +++ b/rss/CONTAINER.md @@ -24,6 +24,12 @@ Kafka topic as [CloudEvents](https://cloudevents.io/) in a JSON format, which is documented in [EVENTS.md](EVENTS.md). You can specify multiple feed URLs by providing them in the configuration. +## Database Schemas and handling + +If you want to build a full data pipeline with all events ingested into +database, the integration with Fabric Eventhouse and Azure Data Explorer is +described in [DATABASE.md](../DATABASE.md). + ## Installing the Container Image Pull the container image from the GitHub Container Registry: diff --git a/rss/xreg/create-kql-script.ps1 b/rss/kql/create-kql-script.ps1 similarity index 81% rename from rss/xreg/create-kql-script.ps1 rename to rss/kql/create-kql-script.ps1 index 444ad8d..ad5a141 100644 --- a/rss/xreg/create-kql-script.ps1 +++ b/rss/kql/create-kql-script.ps1 @@ -1,6 +1,7 @@ $scriptDir = Split-Path -Parent $PSCommandPath -$inputFile = Join-Path $scriptDir "feeds.xreg.json" -$outputFile = Join-Path $scriptDir "schemas.avsc" +$inputFile = Join-Path $scriptDir "../xreg/feeds.xreg.json" +$outputFile = Join-Path $scriptDir "../xreg/schemas.avsc" +$kqlFile = Join-Path $scriptDir "feeds.kql" # Load the JSON content $jsonContent = Get-Content $inputFile -Raw | ConvertFrom-Json @@ -21,5 +22,5 @@ foreach ($schemagroup in $jsonContent.schemagroups.psobject.Properties.value) { # Output the merged array to the output file $mergedArray | ConvertTo-Json -Depth 30 | Out-File $outputFile -Encoding UTF8 -avrotize a2k $outputFile --emit-cloudevents-dispatch --emit-cloudevents-columns > feeds.kql +avrotize a2k $outputFile --emit-cloudevents-dispatch --emit-cloudevents-columns > $kqlFile diff --git a/rss/xreg/feeds.kql b/rss/kql/feeds.kql similarity index 100% rename from rss/xreg/feeds.kql rename to rss/kql/feeds.kql diff --git a/rss/rssbridge_producer/rssbridge_producer_kafka_producer/src/rssbridge_producer_kafka_producer/producer.py b/rss/rssbridge_producer/rssbridge_producer_kafka_producer/src/rssbridge_producer_kafka_producer/producer.py index 6b9c62c..ad06d63 100644 --- a/rss/rssbridge_producer/rssbridge_producer_kafka_producer/src/rssbridge_producer_kafka_producer/producer.py +++ b/rss/rssbridge_producer/rssbridge_producer_kafka_producer/src/rssbridge_producer_kafka_producer/producer.py @@ -58,7 +58,7 @@ async def send_microsoft_open_data_rss_feeds_feed_item(self,_sourceurl : str, _i attributes["datacontenttype"] = content_type event = CloudEvent.create(attributes, data) if self.content_mode == "structured": - message = to_structured(event, data_marshaller=lambda x: x.to_json(), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) + message = to_structured(event, data_marshaller=lambda x: json.loads(x.to_json()), key_mapper=lambda x: self.__key_mapper(x, data, key_mapper)) message.headers[b"content-type"] = b"application/cloudevents+json" else: content_type = "application/json" diff --git a/rss/xreg/run-kql-script.ps1 b/rss/xreg/run-kql-script.ps1 deleted file mode 100644 index 79b4ab7..0000000 --- a/rss/xreg/run-kql-script.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -param( - [Parameter(Mandatory=$true)] - [string]$clusterUri, - - [Parameter(Mandatory=$true)] - [string]$database, - - [Parameter(Mandatory=$true)] - [string]$script -) - -# Check if kusto.cli is in the path -if (-not (Get-Command -Name "kusto.cli" -ErrorAction SilentlyContinue)) { - # Create a temporary directory - $tempDir = New-Item -ItemType Directory -Path $env:TEMP -Name "kusto_cli_temp" -ErrorAction Stop - - try { - # Download the kusto.cli zip file - $zipFile = Join-Path -Path $tempDir.FullName -ChildPath "kusto_cli.zip" - Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.Azure.Kusto.Tools" -OutFile $zipFile -ErrorAction Stop - - # Extract the zip file - Expand-Archive -Path $zipFile -DestinationPath $tempDir.FullName -Force -ErrorAction Stop - - # Run kusto.cli from the tools directory - $toolsDir = Join-Path -Path $tempDir.FullName -ChildPath "tools" - $kustoCliPath = Join-Path -Path $toolsDir -ChildPath "kusto.cli" - & $kustoCliPath "${clusterUri}/${database};fed=true" -script:${script} -linemode:false -keeprunning:false - } - finally { - # Clean up the temporary directory - Remove-Item -Path $tempDir.FullName -Recurse -Force -ErrorAction SilentlyContinue - } -} -else { - # kusto.cli is already in the path, so run it directly - & kusto.cli "${clusterUri}/${database};fed=true" -script:${script} -linemode:false -keeprunning:false -} diff --git a/tools/clean-user-path.ps1 b/tools/clean-user-path.ps1 new file mode 100644 index 0000000..6988358 --- /dev/null +++ b/tools/clean-user-path.ps1 @@ -0,0 +1,32 @@ +<# +.SYNOPSIS + Removes user-scoped PATH entries that already exist in the machine-scoped PATH. + +.DESCRIPTION + This script compares the user-scoped PATH and machine-scoped PATH environment variables. + Any entries in the user-scoped PATH that are also present in the machine-scoped PATH will be removed from the user scope. + +.NOTES + This script requires PowerShell to run with sufficient privileges to modify user environment variables. + It does not require Administrator privileges, as it only modifies the user scope. + +.EXAMPLE + ./Clean-UserPath.ps1 +#> + +# Get the machine-scoped and user-scoped PATH environment variables +$machinePath = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) -split ";" +$userPath = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) -split ";" + +# Find all elements in the user PATH that are also present in the machine PATH +$cleanedUserPath = $userPath | Where-Object { $_ -and -not ($machinePath -contains $_) } + +# Join the cleaned user path back into a single string +$updatedUserPath = ($cleanedUserPath -join ";").TrimEnd(";") + +# Set the new user PATH +[System.Environment]::SetEnvironmentVariable("Path", $updatedUserPath, [System.EnvironmentVariableTarget]::User) + +# Output the result +Write-Host "User PATH cleaned. Redundant entries removed." +Write-Host "Updated user PATH: $updatedUserPath" diff --git a/tools/install-avrotize.ps1 b/tools/install-avrotize.ps1 new file mode 100644 index 0000000..5a15b26 --- /dev/null +++ b/tools/install-avrotize.ps1 @@ -0,0 +1,74 @@ +# Get the user's profile directory +$userProfile = [System.Environment]::GetFolderPath('UserProfile') + +# Define the path for the virtual environment +$venvPath = Join-Path $userProfile "avrotize" + +# Define the path for the batch wrapper script +$avrotizeBatchPath = Join-Path $userProfile "avrotize.bat" + +# Check if Python is installed +$pythonPath = Get-Command python -ErrorAction SilentlyContinue +if (-not $pythonPath) { + Write-Host "Python is not installed. Installing Python using winget..." + + # Install Python using winget + winget install Python.Python.3 + if ($?) { + Write-Host "Python installed successfully." + } else { + Write-Host "Python installation failed." + exit + } +} + +# Check if pip is installed +$pipPath = Get-Command pip -ErrorAction SilentlyContinue +if (-not $pipPath) { + Write-Host "pip is not installed. Installing pip..." + python -m ensurepip --upgrade # Ensures pip is installed + if ($?) { + Write-Host "pip has been installed successfully." + } else { + Write-Host "Failed to install pip. Please install it manually." + exit + } +} + +# Create a virtual environment in the "avrotize" subdir of the user profile +if (-not (Test-Path $venvPath)) { + Write-Host "Creating a virtual environment in $venvPath" + python -m venv $venvPath +} + +# Activate the virtual environment and install avrotize +$activateScript = "$venvPath\Scripts\Activate.ps1" +if (Test-Path $activateScript) { + Write-Host "Activating virtual environment and installing avrotize..." + & $activateScript + pip install avrotize + Write-Host "avrotize has been installed successfully in the virtual environment." +} else { + Write-Host "Failed to activate virtual environment." + exit +} + +# Create a batch file wrapper for avrotize +$batchCommand = @" +@echo off +call "$venvPath\Scripts\activate.bat" +python -m avrotize %* +"@ + +# Write the avrotize wrapper batch file to the user profile directory +Write-Host "Creating a batch file wrapper at $avrotizeBatchPath..." +$batchCommand | Out-File -FilePath $avrotizeBatchPath -Encoding UTF8 + +# Make the script globally executable by adding its path to the PATH environment variable +$pathEnv = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) +if (-not $pathEnv.Contains($userProfile)) { + Write-Host "Adding $userProfile to PATH..." + [System.Environment]::SetEnvironmentVariable("Path", "$pathEnv;$userProfile", [System.EnvironmentVariableTarget]::User) +} + +Write-Host "Setup complete. You can now run 'avrotize' from any PowerShell or command prompt session." diff --git a/tools/install-kusto-cli.ps1 b/tools/install-kusto-cli.ps1 new file mode 100644 index 0000000..85da713 --- /dev/null +++ b/tools/install-kusto-cli.ps1 @@ -0,0 +1,86 @@ +<# +.SYNOPSIS + Automates the installation of Kusto CLI by installing the Microsoft.Azure.Kusto.Tools package and extracting the required files. + +.DESCRIPTION + This script installs the Kusto CLI by downloading and extracting the Microsoft.Azure.Kusto.Tools package. + For Windows PowerShell, it uses the net472 version of the CLI tool. + For PowerShell 7+, it uses the net6.0 version. + +.NOTES + Elevated privileges (run as Administrator) are not required unless permissions are needed to modify the PATH. + +.EXAMPLE + ./Install-KustoCLI.ps1 +#> + + +# Step 0: Check if Kusto CLI is already installed and available +if (Get-Command kusto.cli -ErrorAction SilentlyContinue) { + Write-Host "Kusto CLI is already installed. Exiting..." + exit 0 +} + +# Ensure NuGet provider is available for Install-Package +Write-Host "Checking for the NuGet package provider..." +$nugetProvider = Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue + +if (-not $nugetProvider) { + Write-Host "NuGet provider not found. Installing NuGet provider..." + Install-PackageProvider -Name "NuGet" -Force -Scope CurrentUser +} + +# Step 1: Install Kusto CLI via Install-Package +Write-Host "Installing Kusto CLI..." + +# Define target folder for Kusto CLI +$targetFolder = "$env:USERPROFILE\KustoCLI" # You can change this to any desired path + +# Install the Microsoft.Azure.Kusto.Tools package via Install-Package +Install-Package -Name "Microsoft.Azure.Kusto.Tools" -Source "nuget.org" -ProviderName "NuGet" -Destination $targetFolder -Force + +# Step 2: Determine the correct tools directory based on PowerShell version +$psVersion = $PSVersionTable.PSVersion.Major + +# Find the actual tools folder by searching for the first match of the package version +$toolsFolder = Get-ChildItem -Path (Join-Path -Path $targetFolder -ChildPath "Microsoft.Azure.Kusto.Tools*") -Directory | Select-Object -First 1 +if (-not $toolsFolder) { + Write-Host "Failed to locate the tools folder. Exiting..." + exit 1 +} +$toolsFolder = $toolsFolder.FullName + +if ($psVersion -ge 7) { + # PowerShell 7+ uses the net6.0 directory + $toolsFolder = Join-Path -Path $toolsFolder -ChildPath "tools\net6.0" + Write-Host "PowerShell 7+ detected. Using net6.0 version of the Kusto CLI." +} else { + # Windows PowerShell uses the net472 directory + $toolsFolder = Join-Path -Path $toolsFolder -ChildPath "tools\net472" + Write-Host "Windows PowerShell detected. Using net472 version of the Kusto CLI." +} + +# Check if the tools folder exists +if (-not (Test-Path $toolsFolder)) { + Write-Host "Failed to locate the tools folder. Exiting..." + exit 1 +} + +# Step 3: Add the tools folder to PATH if not already present +$userPath = [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::User) +if (-not $userPath.Contains($toolsFolder)) { + Write-Host "Adding Kusto CLI tools folder to PATH..." + [Environment]::SetEnvironmentVariable("Path", $userPath + ";$toolsFolder", [EnvironmentVariableTarget]::User) + Write-Host "Please restart your terminal for changes to take effect." +} else { + Write-Host "Kusto CLI tools folder is already in your PATH." +} + +# step 4: update this session's path if the folder is not in the path +if (-not $env:PATH.Contains($toolsFolder)) { + Write-Host "Adding Kusto CLI tools folder to PATH for this session..." + $env:PATH += ";$toolsFolder" +} + + +Write-Host "Installation complete. The Kusto CLI tool is now ready for use." diff --git a/tools/media/eventhouse-details.png b/tools/media/eventhouse-details.png new file mode 100644 index 0000000000000000000000000000000000000000..5141dc7eaf63ea3005c64a64a7f2c72d3600e3a9 GIT binary patch literal 18752 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 PM{sgd%92&$UjqLR<%oM= literal 0 HcmV?d00001 diff --git a/tools/media/get-data.png b/tools/media/get-data.png new file mode 100644 index 0000000000000000000000000000000000000000..291d3c73af0cd1ac6837880db371e2bb27808231 GIT binary patch literal 57298 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%0D|8?s635JIw*M^ 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 literal 0 HcmV?d00001 diff --git a/tools/media/inspect-data.png b/tools/media/inspect-data.png new file mode 100644 index 0000000000000000000000000000000000000000..cad4ed79822c772ea3a556076a17a47bb4f561c0 GIT binary patch literal 43210 zcmbTdXH-+q8#QVH1(7bI(v+%HmEHv@O7BIwbm=V+dX*+s=>!C%_ZC{{BGNknLdVd1 zfB+%n9)AD#!@KUMyDn?7LMCL+oM)ahv-h+2M5?LC6F+$N;MT2M#2-J%XxzGWrxN&; zCAbH)pxWrcz{_nn4SDHX6~nY!z#BYkDP^f!x2ofauFUX(_k_+L^xbaVqHw?Yy}f9~ z;C1U(k;z9HDJ?JKy#@SKN;u-r3bm)_OSP9=VR!hq^YP_WyiA z&oHTunL<44e{U^9C7IrRWbvW>FXrTZPygRH_`kS(82(=@6YkVnk3b12S@GaCasTV# z(UZ3p5yUhCoNMi=Nw5C*_0N*nlkZ%g>WY^6w9_s-gOoJ?n+fs^e!FBp>?!;yCK5iL z`@fOulhc&1_BnRJnm*BTI|cr)Kx9fX+rB zqt266Las$Tw)K$xm)x99TTN0+bKy+kGw~nS?E9jqpk_NzsB-Tx=nUF&&n-ghVK^Nq zwdL39cKG3`(AbvS`e3#9>2}i*5OGR~=l*=tbd_26@+Y%7M8t==bLY!z%)#D9b^z2Q z06W!ou}(uH>F?`Y`e8q{)g}jmn|2fMxHd$z4txdu{hBem3gfX5^gk)UCR1CMm4rPeIeUmn}d?%s|~) z;WMb-%#{M-jLcRxTk2OtT9UO1K$L&kU!H6Uxc>WKH~uT~baSj5f9A_niGFV^okMy3 zbWOE+Z^iVo3A4eKILbuVmYC+PFpdcBJ@lzrak4^ZL4?mS+0$Spk1#r!tA43a`9VeG z4<}mXwW7JrvAmF1v+sdC*N}F`V$n+r=K;9#MXffY7SMiTHr1m(0bqnxTnA0lB1^6b zbm%Llv$3Ka0rO5@pS_0c-Jkp7Ax%27g*$R*!-t&$;6+-Rb2J0!vQ+g`iUChG-F|zY z#1moWRK;Ic$J%iFtDHL?Gwk66PpJ)^gOnj6Q=l2M`zU2JP^>F*ccj{Xhzk4?^O=LY!B}13ZYIQXvl(C;9EB>rUY&OJ@t7CWtSk z<)20O=Dl~y&w8j$8jpwt=SM4=)}QHCN3U%-jOB)%?jhjm0uImS8SN5DD^A`a`7cl- zk_(u8J9tGW?Ye&g65-TduL2R#2huUP*fJd2fLb4_wHiuqLNj{>sHVN`;Zj}u6SGif z|2p8>mqx_B2=S`UX{qh`x#Cu8gGKe;)iT#~ff*AbcR}Rrcbo~8mMQ$p%#4K4-e)@< zw)T)n!GJ9a#KBRE;il}uHvjHlem={*S+qa#iPPqIezeEts98OUwz0c+*j^Rze7qDrUk-7I6F<{) z5ZZ5Cn~&8Rm%rt=m7lVEGNIZKCvo}LLEc1aEpewioRsHWUnov+6o`+hb*9T#KOh;y z<~lfyVKZU(93>B6DEs4oeVtrKHXIj6y$tu^%+zGJ2rGOe+;^sjAQF}#!~!o<_b<*W zdI%%=WS4b~R_~D*j13DIDJFAPx8tr6R>PTF+_hM0^Is=o*H~%+%SHPg&*f^+)-YzS zXkfoeP(=(*Y=R6MwQ1o!6xGe=erB0!>bt2Yq1@V zCF1GTZQk-;x)em}(}`dMnQ1ZUm(TcYmbq&`>Il+oPL-yVKKmMu!yW|SM@mpvzu#MG zZx=u8xZC-ohSz!dozK~q$LvGkX>2KcC{$^_iNdt$pO=md1GFN@&{GGwGtbGFc~bj8L~wI1*$L&Pc8 zuK#%=@s&jSh;n<}2&+Dw@heTY8BsB38xaFgY>$-o_ifg2!GUK~WtIcUP4BUxgXVGK z(;jszuV1Hx)4E0wLx3`v>AAU>=jEE~o)pd)fe7z(Y?+m&`PC ztcLoxJJyMPa@$qfx5=+Hg&)4dpK8#~A9~&?P(jQdC$EXObe#aLyN+RyvsrX%#~QXI zGx(o((orPuYH2y2`kt?0tM{9Cnq3m?Yt%D9P(Nd#UDPFSMY&z3Py6L4$amSQ<=;Ze zZa><%x|N}2f*ZWivpn6kh{FnsuFr;-8I;!Br<^w9Yfhj?2Di?-XU3*~sThe?Y(S@T zjqlQktuWBM{V0FeVkq}1_1;l&^LY3R8l}Ou<+KQcwzIPZAN4rzW-Jwl-CJEVC zKD^{p0z2I39VxTVn?A&CnI!*E__0S<0>)oMhKHJ2T;@@P`--$XB^3}O;=n;dp(Kn!c z=l?)|3Wv21iyTUjuD#KxmL$EqHZN%4(uhN@4MTYwW_!4YhzfbImwwKQZ3z>sh@otl z!+p@wq=Y2O6|*wGvl}|pP|Fr@IoEb>XYpEBLgWh_t}72JpF+GhF~L)t3=XPol%Nss z^0?k!EGc(DRM&dgj?F#hH2R!?n)qso*G+A6OQ9sqeQ7fjKo#H!B^BM&s$ zW+mcIJy6ireOgiUkoAJO?3<+()g_ZEn4$6EG^zrXDfp77>;U6sf)*OAJ%Z@Y476XH za_Ce%T>qQW->hhL_*9-v*S>B{PN)8hwqTZns|bw3ca!-905FJY1E;+?(=70Mnohm~ z72FORMs57^k!fdaH0dF*KFyytqQfcE;@{VcRljPVo}-11T%gnZ)C7NoRPm+LNNheUXg}fS^e$_1QO4kRhp^=r71?!;QE4 zm3qc@5|d!#xxvc|unG<~FV|>6bBz23zB;bvHEoK1@VBRPgFGlvF>bUkn50TAk?r#&nLs;d$71r#*>qCE#NP}R`HHG)-a>?w>ikad!YXpW&?ZYDpaOETx^_0vs6C*^b%2Ei zG$=3Z^m@l+i!(K{;Jy)=d>cM6{iwDf?sA0Snag+|0G$J8n`egQIL4%NyB{}d1?Bk< zXMmO|(K9Bz1xPM8I)moVO|7rbMO)6g;Y7i253J_ zOt{$@84PVHl9jD(BKx-wF9Cc(t;L3YcS^BKwrTTQn8m5>!b%jgTWh54bkK^1`eQF= zxm$KW-!$h05=#6fRF$v*Ye~$G8G1}+x&*&w(Wd3PsW!5P^dqxPFRN9n$3!6ePOsSzUUf#W;6nF`b8h@kHvi!ah9$f}s zL*+@-yPYCQHRmF0GM$oPq`^HZpXJh^aj}Xp%@l;^*ie`83 z`$)sVNYk`;o#T#3ZYwYBa7USa^9dLXIzW(d%Nqdp2@! zrY4D_Oto@hH*Vmds*`%&hKaj%NV}b5qcy-t{KL7UtMkBYyxfR;T0o_ zxW!QR+{;Di8y)o$S=UVUUhRm){(CI2Dm^GzH+`G!lZj>oQ_Impe2$oa*&&sCIw)g@x}uS$wR{ zSH4W0J~Jzc8srTlv8=G&jW}rDshGOMsa+h+(>Bvu;cFJyuiT?M zjzVg3?aaxKveo_NyKzQBA8H_1)Cz6PZlXcYE1HOgqOJsx68>oylFPUskY|mO+ExWY zdkI7a@`64B{SkLK6uX7UP&JhW&O zSFs824c{47+A7+?Uj`st`u@w6=)G^n;M*}O*02VGXh{0HAZ}H}T5ZN#^Wh2)G%mcew#^dC-`Ok3spD3zG*;VlL5p3&(zk7_y8u)2zMm zri{Is{d@bMQTN~=B&`TodTu8x3KWw*qbZ+d#Rfav{33}{bZ%Y8!guq{M`|wlQ6t>y zV``>rZd{1}lNO?{)NcO_?pX0${Hu=luq11&8xDKvf~s9ZIY^63{3sT=Bn=n|=WAy= zC77&>K~8G0WjY7bxedOlNKA5=nN`mzh#FdPYG2e!EWWOB=$>(5E6M$;o^yn@?CnJ{ zcM0SZzePac5tc^`HM4;Z(t$|D`?r%F+*ZPy z=4bB}?H(DgZW2gEkx`L^FXP_q<3uR0eC8NfesfA2DRCWW82 zV_$e!bEy9(K7zC`i*$?rfOHY}d~{;^ykW^dx_s3t!>8@CgT!ZB0wK(^JIeh0Tb27e zU|TWUirI&C32gZ!iJ$BhLS-=?Iy>8T0>}PvHVdzTd z{xA1EHS18CW$p19e~ca61@gPghE+{e%lXJgf zV}{FG2X**GeX+ zv}>>+fxhj-PtUp-j?<(!8S5zYmcScy4R=vPLm&wR`;Hg?=sf>k z;z%S}Qa{Zwg=g6uWP2wVL8$GE50AR>oU+~ho$bs7_oon!2(&XiC;Elaid)O#*=!4b zXH3w}Po@-77vrgZ?J~LG*H5O(k)JB)w*Cp%F7Sl9%=qaovJ4Sk*|rslI0h`mfG#;y zXMDhB&2o#^rtskf`w$q$N?Ltmq~{Vm;5GBd;17wBL4}B{rpQiK$!U6hopqeZf{ORi z8#Hn~3Scaag*vIqMvmbgb@qTw#kpRd^gK0E1ok8S?}aqR0*Xe75+5cno0H zMaFV*B!}01?y?go2eXT81$Vq)oSQVq0GT-B-2h|jYXxSwY`t&Ind+2RNG(D1p!Etz!d_=a+rQN6=7|>5deqK< zNfCY2t_zQOFdTn)GGc-V73MYKjao^W|H6<3sy-DxeB$}3dNr5WuKVYgK9t-DXt|t{ z_S$KwG3|8W-~$>q7G!lF$Z2;qkAUNdiQSAh0W&+`&U)E}W6ji;2d)Az4XV659mSSi zlInz@=Lc<=3dBd|QdY|c;X~)k1$3rfy}w^f+l0U2(GM?3T<%WbWm4m^l;0vfaQ&OK z?R;Kn)V=D@7gWNv=O^Wy|KO=-0H{vON#DfzQ@Iw$Fs%xblVtbmf^l_ZFkacqNZ3yY zOjHs2&UnN^lCuMo5+&l$47YH`S61?kXXd=PHQ7B&u@^LCzx%Z3zs23HOKI2qsk|@zl^j)>|SBp>QN`Q_QjLqr{oeb4A~yn1LY>u z_A*bz3O1now3TaC<=cL$8H!y7>YI;#=Xl1APNGq0L&S)V6q!-UXHXA5pfYm&8U%@z3WDO5^5j^WFs(5Fa>wUme-4!CWpZtQ;C#Gb zFk?+bxmqk6C)|}qbLEhuX|9|qKH-s?ODOFE7pHSq^Ff|VOc(f{VWWO9C)chdb(^te zdF6`w%2r-u_FG26pttYdYt+7CC)pPf$H+9Q3ranXNc#s`o~|yY@$Xa__bx3 z$Xj@L-ee&TN-ahK$Kd_$v}dU)9u}sV@E~6HKrpG~m9y>(MJl=mAyK@VdT&ko3m(qM zbSbh)0u`-4-|^>_R-@HU?C(CjY9~tuh;?g^Z)S27ueP&<20QM`DL*)VtKH(5B@yG+ zrqg!V^8$8B^0AJzKtCqH7)sh1)BA6L-sFisR4U|N6XNOlop;akKX0jOQ-_bd4G_vg z9*;=9Gp3Yx&Luc-pEgg^lZ1vGXm+@!=!7>ZZPqS0R`{`QJn;M1GBV#JE7-WFfv7vs z22JvkK6V#)V30};9ril?xZ{tp+`q~b759o3)t<(8k~~l$mvutBU%0hUuoI@Z2w6Us z)O(kIGGrEFgqWIWn4JxCo~v^7NAp8JE^#tGW4)Dii|2#gu&pyOs|@Gn3X45A78HSRXnEtPymS7XiZgMxt+_I)aD#F1NTSet z&?i%1daLf>Uqq;h6MYEUw1!oHPx5$#NaT$xgM^*0HD}w8W62H=_98LvyXc&}R|BcL z!W}sJxIS|?ll2WEF9E#wQ0lt~2oEB&I&kFSwUegpS{v)pdwf+|{}Mk*P@NI>+HShW z`29}6`KyWvlEU(4-;ROK%u+R@e6G#+t*TWUu@d4u1W=DD$zcKKC8^#|2sIw8R_Msy zw$D|sEut!t$a7idO3T~R*z>N>ek!lwIrHJzRy2t^51o%r7xMWz-Arp?=_iWcq_fU$ zf}t;UX$XeSmXzK%vozh+aXQk?TK{|Vsp0o; z1s>bYXmq~lfx+vME0$;@s!U$7s=PcJF?s@1ZV9|1|n5`i^nuee{Kw`SV|0z8Gj zLukVng-5h=?XQ`{+s&b|#r-ICN_N`sJT3(Dw<6 zuREvVovFVJRb8qNsAv{VO>{!|!&{)0p1YnhuURAmUHwO65Ei)NP?@N;s%{dulwF!D zvNn1)5lC=4PbN#VYUU>F-@^btc7+w~U%{(~JXGGXw4-N9L0=fA_=D}hc556I;ch?`7TC&@qkj7a(U4H$z)!u}P7YLafkI}rwno*YsR@`U;CDzdN3_)5O#D+BGc8d_EV zK$5=+m$GcgfDb9rV0yaMM;9~wHc-3{E&0J+8TS-QS{qY&yl_5JO7M6)TqkA~! zC!g!rmp<1E2-hEy75E!9ERiAMQFaT>9t$HAc*!-7P z^C?U%J%Av*cyt;>*0vCbx}CRv2TgOlfx$9Qg3Ww%hEBrG7&IsE%bjQdGCgJDo;5|x!1g2Ke8Xt}TaQkq$XfwH zzweg?CPQW|!npD;@JUy+f1nHxAnU)C!ek7pc_q1WT$+)!Wo?Eq`EK>zw7-Bkz1pT& zagnLi)dGa>pu_v&63=C1e({B(-^{@u0fM*|!3t@_X1LtE13_GLM8pp*bxg)4OV?VW z>WX%Mz7}ql(ob!(TUtg&;k`SjYorV&Ws^^m9x|fH*P095*MnD=aU-Wu*JeOwTXHxq<@u?P-9$$5 z>;;);2JZP$2;i|OcvK(v5xVpdWFVUdj3O9U7Z`t=YP zIT;YkAB}!WUWOXLKO+^`8E!?ckA;Vu0>Ybs^)RjHD@KiUg&N6{zZlLi-QsxH(~y-m z%ziDUs@NFt+G4735wE;+dL!;$Y-BsBN?cgHmX%@VeWbt(sMG9aG7Mx&JbR>Z)>+^` zVfDZY0B2RrqE$+&sr%gX00Zb*d)uXzP)XbsZ|WC7#eZLF*i^&sI4_h6B#v<3*_-^< zgI7E^QyhU&J7i#7$*CL46rT7>Lbv^AV;Euw2$wB1DK+)(TN;?loytAHwZe7Md{Es> zf1`@c-o8&urUcv}Y_pB+O88%oGG&EZ6>50zPNDQN zBkbr86sR{Lh>0wTqMI^&@rDT^00Hnpa%Iu!9H7I``?`E3rqQu6+J;v;0XJ2<*R+wf zU#(Xly5HE%-*di%yS4^qsuttgQBx%zD|zkJpyUtfK4&$~}3??We4M28lAQOX!#h-IJZzd(T`qPBMeGC}fe zQd70bA@DKRrx|@~h-JA!0|+kr%Xc-P4G{D9YXe7Oa_@!qCfJBkdZYL0Ft8Pu(BAJK zJtThdRW>(J-div~4Llb-$^jwx zY=Eb|@o?Q^Z*FRPve+Cz@+muX2gJ|#{+8c0`{8_XV?`jv4}KipMQ9sZ6?FIhJ@j8e ztHCGKV#NftzM<8Cgg1<@L1qZhJx2_X{6@DHExs$4$;Z)i%Y5$t@d^Y?Zex|w&l@Rl z0Yy1Z5dXolmBI`Rgvb~zwo}>OW+0iB5&wa$^l;~oyR?v0+C@6Q-FjAtnra79WMJeh z&yORnVXGjc`893NTHE#I&e?BD)fpHVWuF%#;3}2sQc&&J?R5o6h?5I(@Q49`&&*V| zUvE1W`f=U%nX9w?uO`3u`z%v3psmG7roa7gLz{60tdZ8vSnN8bt!qT{E&2n!1oM-k zHUXQ_=c(yW@#sntZ>p$70={?I8Yw~r5ca&(oM6Y2Xut~AQ2H_pP(PtPj}00Tgx*Bd z-0o7PiYeUOFI6&y#=>|?JjF<)B721aKZDWB++0OurQ61^BOohA5;fu}cA-KEDGlqP zfNKYIQ&KD8oEk}Bl5c*%_M%q1RHtIKAM1U#Ynx)|8d-W?V;Cw-_MEWLUD_NAc!Vr= z%4%b=hux&yw@`+m9l6t`4hZP}QI`#kQhhS0MC{rhv$wIYcnjGk#uJqI`VuJCHE)<> z)IM5DOk4ksAm`@u+#Ky3QgmijJBHm<1&Ib7RsqCYjtH@+9q)d;5fH8sD2M8){W3CGdW zceC-YDmAq}2s{^|ZukPtt91yT%4dcUTHCJ5BCE3Ypz z?~ScU|DbtCt%-?m8n7OWu7J9TQ9hxnT{JHcp0}8OtB)~}0UnXR%4=1pz&u+3sheWt z+=+komnp8XdvgqxO7YA9YQOb|u-(v_J~`u^+$Q5g%=;6wP%HL^L7$!ShGtgshl2CY zAqLqu{(}C`>^oG}yED}l6iQE6wY)ibf-*~9$L&@7wtAnk>#0a{nI)gDRF6x=Th12$ z!0g>M7G$5qvx7Ft|3x;z>fy!+uKPo39n_3%FUj0(1-h_cuBS4;R$mTbmBEFF>>6@H zFjZt+m1_@`Zlkk2jcPDkPSiFVgH@ub&UoNdkijRj_yAXHn-v_e?K}`2#vqhT+VOCm(`dNUO)2$sYT*w*6#K&$6N0sN2~zx*t3+>ycTZ`V5{hUk66QSY<8xY^uUF6K;!0AL<_teC zmJ9BlbN`zA$s6$G%t>H&%^l|IULCvSUA-m0T9tk*RRP+Y7Rc^@lf%V{>1KoWP|+c zLhG9NAxqX6HQJKS{0o4so~loCj^Vl1K~a?J-^{3;r`DP3uQLHHc;8tle9=~ZPhA_K}#hzh#2+Gr6K)??s3B>-;au!cL$q%%3(gRaPejNiKqX1m<{#%BPKMj* z4;V*e$yheY$AwBe!x{WH=hi60MeXvN0to9XRtzI0K4zy=fz2%G1_liyZNN|ZEdTq zxsqiv{7I(7Hw8W$jSkRf>}*?|8wk$CFGa_u~6F z1NfN?i!gvbyHMk-GVSc8LX|WX&E5R>bh40(OPQjmn2_Sk16Iw;R6Y@8_ShhvOcd-yTy8?d6q{)BqqVfZ+gS z``_#TZM*%!QKx%)<#qmcO3DE+<1$Z7uJc#BuWKW3oWL@!U;pP${rB+yqp>yf{}^Y5 z^IYc%=lE?#<0Wsb#vp*<{;xmw%4dAcPl3OgTeQ-F?eJ_=!!h)3Ap@yNfe5Eb+k7&o z{%44Yhb#Jq%M=5i%uhq<{N(^_+i$qiq$6v+S<(T-VYCTe{XNF|o4t-c1B9)< zr4kt6M@t{Cg&R(6dET^|CCE8t`N5-2Xbi&+Q)r^_7sUYGmW15I!r~J&9NtYLI%ssc zK`d#VyP?2G*XJ0mU~LR>_|Ibe|086m|LY>}3x-i5K4a1?t{nqs$jv2()lB`)$&>n$ zrBRS!L+L^zI%m2{XV0`GBH|wfWaIzL)vq7ExDlHjj{}dhtDjDaj||^{_wCU_VvCiO zz4tT$(#1{>&|8h;6IGKGp*p!EFKj!Gv5}RLQR4{k*#1ZiGMB?QPm`6^1!!2V#!az+ zD1~dtYif#y*F1g5q?x%9YQ<&PI65r6LE8c#q2O0(ynvAwKq%PVS?g@#f)D!X!fpi+ z08)dFdZ=6AO)p_8^7PIpRsKc0`eQFTu(+m?|9U$Bj~(Df zp7nWg5_49AspRvFiC`c}^M8Wsw=33kZS~U7jUJ_Nf(n*`LpBzv!k#1!-Ft8u3V6X8?Mei)72Pxlix)b0?lz;}cN0sF}1iIIy=qo8xL^rRo7-+Acr@>UE95EU7hC zH=D}!0q%Olu^kI4HS(Ey%6*T7)`r^1UA{*-dIb9@mY36PrUN|SceC<_S7_nXU(#rT{;4bH>|pG}rgDJ4V& zLpI`Hyq~uexCH#q_JBDs-_^nlK)3?lCpOx?nm@P>l4fhI5jWJp4|CS}W4<1sVKf5v zshH2tXBAhpnFr=Q4_!cVl}39xP7>7_lKvd2?2L&Jf{{>(gc`v2ohVB$yvryAulA4eRiwEjQ~t70C=-ahqY4=5*4|tThWUM&?4B{ z^8#>kvX-5lL!s_9kx@I7@00c>R3+=zVnv5RvzF8ioU|obyw)nO<;}Fb=)E^zz$;>r zD~UTws`w**fbET{jFb)Oe>$b>Fk53;0oedtZq~rk-v|()UrTUO5A?d$JRBnthw@ZAsc7M$B)pl#*HtO{fU>sb93TNX#OfmMh-Ni_8pkFEK|7!L zt-w)bwZpE6V9UrhL9p+>BJvclSGb{G|MpAnOV?&O7)r)fP$t~LV-HpWAYt&Ut(LtB z&*17wF`vPwpm*pjP)}gW-Xf1ALBXFEixj_*>fh%bZ1xUSo%g2m3Dpj-326e1K?^E@?|NYXM$J+N4B7%qzHWk~ zowb0A`-ZMI?OcN!0PoEd36pCCKn!tpK=dc-^DGLF0G^1rODbkcC*odpW0r-^ec=#X z0v3h6;NM?q9QCTMP#Yr+9F?%~uo~bwTH2d`Cg`|39VXxj+>yeZx&>g8u4r8cc=`Nr z{HfVf8{Q9k>rHl(MJv!Tk)1MgU>|s}pSBdVRa}_m+8+DfX&cxFn&LsgL)l{atDGT4 z^6D^z_{r;z8+HVIEun>HhZlf5H2hzFASCLD=e^cqjPxup)&9UCiYiv+^ceuO@SiZ0;l$k9k21SLfMHq&p%o*5W4yBGTyVR>e%y3wM3#)8vN zmwZt%K90uW08ys$cDOMp8#4iZrvVkwJwED30B72o>t!|Q1#)D(mGp)T>@)O;)H@)i zTa$hDS1$-R4eYDKZjLUnDy1$b$DkL0)pH%nzoSHXPg)M}%ReyYn0_?{XNg)K;!Xeq z#CUJ95FjVXcKsa!hX=D-^x3$yO`M#_z#r%@?7{ib+FsyY66c&RHzf4n?z(vsMXRn? zxrQJ8^}$7#PJ^RS!va9GeK0_6VF63ncSVXp#yx0vABbAnkD#@s-D z;An+?O(f>wGA;uH6nht1d9c=$4#i;AiR6^!g*w{_>1+d_p3@4PE->Clg+s?+*RTK# z`ryErr>*RW`1WgAixzOH9xJK zUcZlRz*kI}nMn&%Wji@O^0P;CiJPmVVg?)HRIA%#7*dp38VeBcuu`jc0Szu;#rWfP6R6@r=lOeEr$ACst{4onqoY z8&&}vGU)*=`FS>o?Y<=RcWOONE^oiSAWzvNn z8^hOPz3TVY8-Lv{E!my`g46Et6`rZIq^N(^-7>+rKJP=zz|l@v8HcEeL|s}69fzo0 ziPUZ;;pUAQ48cAT9|s%ddX3Z)6PV)BE;7JyUPH4aFqL8n|9PBT2^z^~ ziKlSgo0`qT&Pmi6h10+GOl;K!lFMWkiTj}#%#1qr6%#a}02{Yosjt9e$dp*zfRjPa z1M9dYf@_$S@7T#s2Tt;K8oNj(?+QFXK;38qOSylDbTV(bc`hCO^cfcK!+88Jx7Zr8 z@O+cA(f9{FhnQec)1c~eWNUYa-N4zh;#<^FQ?E}fkAiQ(p@c;mFO^}!-pXm#P9-$J z3TK^U^{u+SfV<&xh(@m-w&gEug*}aqp%sOf@Y{W<4>3n8WnaKeF@CFW?M4{`{A(=* zocblt;HfSG{^QJOeO`|_`wS=ka;b%9Io;Qa_Tz^zY!@tjI(JTqMtqwGW8KAUpjTVZ z4>FR_nOjX;v;TWweoSv(GW1EUXM579*y=8$WwBzkz}cUV8?!ogl{*#i3ghlY;Ztcu zzMCLsX#l%7n|-f&D?f(RLE^7CNXvJ*w)-@Esd$EbRd`TNyMRxPka1G2+U%*A#0+8K zit)adCP76g6DZJ3X)Ri=#&~y` zzc5M#bw{nx5lqQS3z^)T+43$U%6SdT3cUw9DWi#lJd_HHKLl27>h00rZ<)JX$w>;7 zGjyCAQ+cShW(Y+?^#fAV=)_lIOyhUoe2+8$&O(Vc2X?QlC4NrpK9FrM?{?sx@H6W2 zvWF6yP;@EV=rIKF97Dy|1&OG>M3pn$T!&8W-d`}t!9OZhZ#P1nEA0D`CLe#}>lGu$1;dw7c zKeecpL6_uNo3epr;Ing#p;>3?MWXCga;D9|@C~=7QL7O`&yq}Qw+&=#1#!CGHQO0u z#tDXiMjYH$UN$j5*W3@Xv(qv!9)g?{64Qte=-9nzwJ(XGZ}0j9nw@D)h6FcsbbVxU zIA5A5_gJ)p0XVUIxF!;ujhX;ZT>tnB)p>KKLY0~n)lGAR=l17=OxGZX2{Uog{ig6e zq)8j;I=dfU)M2>L`SXpC#q2wgRqs!8^lPp5y=|Yf4nlTtneXHL76%}Wiy+tAWozlM0ckEKMUx+0ihmRAI zuF$a&z}pnI$X^$^7u2Ab`6x?@(DASiaC@B{oV(H5`)1$36*>PAC&dLwR8fcH0`f!{uw}OoC>O)WfXBambzT0%ZJ@p3 z$rE&HI8Vs39_i8-IHJCW8rS!Bi&d`1WaUm%TnD_K#zo>6u%`mn zmgO*94{U5UXCw>1)_$?SU#C*tKg_%D*Bb$kYJF^di++PjdAa^#TmHxI$%#JKR6%a~gYEgS(#-^4&?niQGo=Vq{Ty#{R>g6D% zr^&sg(7^X$T17&kLnQG~7h3j>Ll-Z$k25*SCiCX%)!ZLzzrO^X?79m-Qha_0=@2r^ zc=#gdbfrpSN1FfJ`wFd8!m3c-k_xSrb4Dqa(nf`6UWqT_e_hV>_!)VT#NHWo4;+5y z3toBcw$$clWVy)Ex0AK)cacq?TQ#ArGxFUw{|MZjLMqJ>bUGxswcDGbbEmpY zquy*W<$>In$p&vQgGaR02)~KB(Q6+d%Mp`v)0Jid0kIcXOKs zSJw+S65H`J9ucx_ileEgAVU|l<@0|RU|UZ`{MaaF<(ERR4;k;`EZH88TfEq>hAw*B zp@q_98gsc`?Y-C%lS|qLY8@U)buxPQlEY4){~T8e-1$jKibxembSKLdCQMp3Opb(y zefb9f`Q14o&B*-LH&g*X{vBzy@|b89WgdqW3yp*6W37He^aC;BcYT@(dd2P^ls2-y z(F)&6?V&Cn|Km1R{N3uV?-o-BiY09CU7?(Qz6nw`+k>gTpH6w*RsJ@}pnl+?!JTpOKl#&og>XI$_k1jM5 z!9?=wZy=}^c5{YevGWLa;*A{73n5=gc))1JVWjn_xW@TBd-$&GN|TV5ayS`#)$ZoZ ztdG0)GU$jU0vkw`9kJxBJM*Y(P>Qk4o(8?&HNtg~e`jjmUc`gES^&$57b6Jgx6pGg?3*8P++l+#(yE!q3l3cXF(S7A%Vj~}1TFwBA6H_aA4oDeRAXMEkj zp8hB2z^I;Pa)>ArtuFmACn<_vlmX-mXjkc_Vj8DRfi=9VZwRtX z?|;niMSoyDtmb8TsowPOjgZ#RiX;7ZNQ5NfmV?o3_1I1-JEbUp#e`;h6oDumD3Ft5 zM78&!h(q-nYVWM*rE37_gzsd-Wv%MF)kcp#{-Ph+2;TO+w@{Ez^viT4q;08*Tx&~T zRTVrPG@%(LnmBq9R&oN=7xwS)&wR~vItHqDE>ucO$?=G8YyCq#6DWgC+-7zLI|CwU zN2`KBy^LvNz(U`Pj$jhcS6ZO8>^q$!QW#7;1F~mIm#h*8`zEJZn)+>V4cig6+poYM zYxQldsE8T`)9(!Ua4vX!>$dCii3i1N{oNXTKe|3}??9?#WlW$R#sKCy-%#H0h+M_? z7f{@ld!wO>e8N%|>QF z>YP{QaPhOmA|+n}_tA-fgAwHyM@rI-K+H8kgm<9xaTBcGx-?*}xl;JrB4I?AiV>P+CXIgRGFf z?lTpScPA7pM@n8yz9nVPwC(%ac^&+bm(!+wk1}d%((3KhdrS0)OKZH+u`N|!`Agr7 zunv}4aZR6DGn|h+R?0R*>1s8wD(`%nno4%cQii-nBv08{+VL~Ks;mNoD<`f>V#++O zx9}fuX7El~4Od!teByg0R2x+5p3DxEjq)`o9(U?lB~7o%9j(Y_^bc^i4DN|tlpg@< z=PaFczWB=(MiPd>%)`vZ-@9bOCQKX2V(57{qEmu1=^U*UUKhS6mbB?miG--Cw->7X&BZbf;KmhsnlO|KF3rQ^^L?=~nGM#3p*!fw+(utT|M z+q?2cpMLt4Z=0@~0}Gy7SoFPaA$!WXknyo-k6{b^WRHJ}cg!L*1!!ukJ_Gil z3xbNl?&3lUY+PX!4i0F`d&n<)Ydg6Qzktq&;K}bcO!i~JV zFHdkZd{0++gGX}NvVGq+<};R9pQ0AO3_KpJDt1fxRQ~mvPfzO;%27|Kmvt!JiNj8i z??KJQ7lZF#`H~@D)~w5~OYMl*l&hP-M-5UFxkT?zX$!CV>R^XOBS_&f=XkNy;H7s>kEUx`rP6sNV4`SJ!wIX>) z@Q_;fWq8QxNAP0XIwYO)X9EzG<{RrV@T$i~0#(y(k%#?H1uh#1p+AomN~d9^4rnC7kKgszbzL}}&d=xbK91wH4)t!C@Y3R3^{nrMcP{-X&up^z zU8Ra`sHM4`2DfTLfrN0Klb+8&P#A-Ss=HhIAwTTb=cD{i0b1MS4C%{X>iKQHT++Vt zc9M)m1=BiU#be%i`u95*-!!}3XZF7poe6sY-Il$zOR#0alsx?Dq|b`k1VMN9x~z6d z?z77nTf7Hav*jNKa?JFu=<>ESOdVbai(Bv9-i&6GU8%RH`K6fWwp#<-Tkf^VbOOTQuh?PRy? z8k0V#Om4QS>s@OLoi3qPkj@>5{Z}A-Zl6C0-6sX2YR&HgISLaEA`1RN5d2Ax_(yET zKhS*?b^!nU=dtcvKdVG*ie*~=zR-pswJQ7{fcRGoBHa%lq64Vt0#HmOh@O7@V$qS^ zcIF#LLSx(NO2f_dQ=rhv^!ncFCh8J8^8w{wgofZo3y?@H>R+ke|7(9u@+yB%s ztcZ3{F1usbvy^rzz1exNw96d7hgx;>ZQzH_ACP17)O=!~Y@yP8cYC8KqiDFlRd|-u ze6ZN+?;qy0>+cpB2(7Ru&Acgf;o-1o8R%_r!5VtRiRmX=!Uc-EIxl|GeHK&2|(6nJe;1 zUjnUJb#SX=qfOI}jzmiOId{Fev~oY%4_ZkJR0y8bw|~GJQc1rtgEd+0@0#DScrvuJ zq+Rn({r>Q>DR0Q}U=8vuK*wY30ahkd<@2li3_77uQeh1pD=FT~d|&QvIjwY+;Oy-Co<|;;n~!d@8rt_=|mICO3IfSpr2c8fmv%E}14j z$NTOwmgwV?yZ*`WY~L-hq8x1rr-4kzjR}JXlgh!dsz9>OPR+eSB`w(1U$a^N*{T2Ldl!0s|73+;+MY(1s+{>wjI_n%4&a+LFxb((t zmeSYJF3UG-gdaCI#<&)e4!riT+PmX8x?yo_A!l)&%XcDDiy&F-rylsHfjM zRIGL9ai}KtPKH06pJaCIPEl=yYa!w=B(VUXxe;!l$f2{G`P#GIX!qY{@F6FeOMia7 z4NOfDFlyDpw$lcUjLzxUg09<^l>jCW;NF9VrOtCA8mL=cr-@+hARNg4EKL-qPIgbg zTPxD5cwAz4b066k8v$fr=YxT(Ccz;R!_cY3AFcd%Am(E*=AOU7Hqw`2#C+nmtgp$G z?fu>!y2xntk!pS!=%Z{TpaL=6{Z}V1TW=V8gYUMYK668EDHU-%9jGo5c zF#Dygk&m;J{ue=zCNN*(!~m><`gB2tUPY<%tLm6_q>A&-h!S%yz0dl&dkNHOwhMKT z{#3f1*W9CHqfledV%nkg0CZiJ{qV=n4(q3b6JNvw;jvEMuk_gh*;_r`CD-rMCj${S7H9yOdWDc*43bf4c|sB&mIQT!d~ve83) zO;RQoexKcpt)Y`4-xjdwZHJ_$A0clWi`VY&29tF; z_B)5W&#`rcq-SN)Yen}&7y1ymQOk3Q%?a{Utg6rz6J>j`*f&EF2!F*SG2Bx3I?$kj z9L_iO20 zC{zVSHEBrXHXIvWmJHK#b-71(h`t-*`=Ur8lA`E$7>pw~=v=f1t3bnLxz$U)HrwM6 z^PW<+AOic*h%zvF^NeKn!eB|>b}cW6Jq2Fbu`Di?s>H0&+%IecHf!#XvX1u65D#O+ z5>4@tw-ZL8758R8y<_$73Fz_Tx#4ocP_O$Za<|t+C^zQDpYL1uI~oQo{e?1SP3*K5!yn0QFktoHg^TfrB{}7Vwd%Pk|EcH2JYtl|{)xE(#<;j>t&XOKX zaOlJUVsp8_$v^G!`antk2_G-jTkSj1Jwtims-j3IUQm7`05lmB0zy`BaJvsA3D=h@ zz2~h_m+M-DLrH=_#Gr8J(X8e&Uzs`jZr7{Wr*^>3mM!LW^L`%-zG=80We73>p z?6nW^kEJz3WfBYhej{A-mWLBR_MU&J{Gc#(Vt*kP zF|dz%c4vDbevIx|ou;0igQUQKg969=#ms{4JBPa_&N2Ea&seGXcwiRxvEi1z+N)jB zUozeIvURtZM%R{m8+Iu8D4=&?`8*(!&P5S=@vK_-@|9imp(a0em zv48t0iv>2*aC&!@M}zdq)Uq=KN!lSd3IHu{H+o}k*^wOYWah9N;2{6XIUow>E5IkRgJ&;SGQJl4%?3vbQfNWo-qd(Og zpqo6O%_XZ^+IIEH*dwRG>e1dFQ}5R1(pO&B8qtBh zrONgCXjYv!yZ6-Gq&NqZbz|{JX!3p#F_Fg6uMHnRO`K9O`5Y#XMx;#A~X3OzCOLK0@K$S@RMrzpX2*-4VfdYr9?EaC_y{r6z-I zsgCj|YlcJ9UgJ{Vm1J(4@x1uKZDcmGH~C6n_>lquqx+6k&v5vc^9wn}g#|1$SBHN) ztwk2Wqqpqy^`d1rnMm@U82_W@WCPjtJ_s-zd>uZV)X}-lcC8?w`nod7cmLBn(4rFb zEO)eq$Wk+e)MCY*^c1C!k&~}hvWu!*WwS`|^JVd|6xvbpUyNPUIdy2VnHXe~E~AB2 zh+-D8VA5TefAQ>cq4A~@5jQ6ub2NklD4R_v3!3tyLep9KV^8?#j8h+a@cpE zHBecm{@o<03kQ+WuAl;){(YC~^{atj9EwBn$MWSA*tq8sF+;|j3Of{(K`B9bI*hXm zN`18IfzUwHsg?ZjJ#U-JdE_Jup2#_jOFkY~rma$N@aw=RjNgpzpqUTR1+Uu}S$z7! zI^a4d?ME!=4xJnIZ#?bjxp;#n@WDAE7kolb>R>s>r`Nhp%}-wF%lV~h+;QU#;|`PS zY5?h3{7acOzi(mg;A{6A!c+vVCaj(qlj9#EnP;!?SPOSL+BU~vcEO!ccI8MR^VFQnc!0D{yJ=5m zWOyrXRMpEVJxikV0M>Zd=BR8hxlR(xmv;xd16F2pIm^lM9~=^A4!3#AZvME&X8B|` zuJ^_%%lppDo1A=2)xWHT&*{l+8k1HPp3b)#zTN-xEBo8E39*n?;je5@qjt)R9Ni9` z%)(os>VC^7_(=F%NPt~Z#YO)b8!Pw9<4cUAdv7-msxLp%9w^4qx#4Pe_V955b+e(Z z7uox7%dASgn=T;SGfJl$2;89BQ`&jBTxuf`GCS|<9pk;R0kZ7ja5 zd3H=R_2PYj|b0*%b2QuZmY^YI=-p`^*K+Zh)u*EbJuFqKpX-% zhJ-YUFGU>kTe%BSoF(3m)t|nx8G9vA8ud-hIP_g%gxC2fkza;4g5Rj#qM{_4jCc}B z&KXhgkBzIm%}+^sS$M7kHEEF)6= z9@SW9yG~O!2wkf)v5_Gh@WM%(GN)UAVUP0T<5U)#urnwjR?q)Fu|`Z7Ehx&~R444+ zwn37bfzOhf*U@_0s+ZlCHa3oKRwsgl>1rs}?%OSCn)3MwPhV_{S>by|y&F*r@oyEa z8R8uk!{ir#k3^*0dQqrf`c=2#>qncVy^mY3w8$&-BS5Z}i8EJY*JBE>(BN3mHk|Z# zc#+PmmLMv@SSfG!f#Gy8Ejb@u&l*#?<;JlkBfNU6`E}>sF6UFnbim)Gb5#WU8nbjJ znnxmq{J9>BXcTdU^9J{-sMQ#e|Jk=QE;2B;xp`bNZC7?Ym$G6%*wlaN)1G&NyqRuQ zOk`E(aLr{jk0*WoQSYbj1p39)l&O78MomvhblN$Zu4hh)6!+yI&%l)XYlzFzShy99 zk>s87uCQ9TmSLE&$sY+|&5)Xt0%wNPJ5DW-giR3CbgsY{t47GA_wzIxe3_Ue3u$1( zj(`^P9yp8w=2WcQNl@(Sb?d*vO#k!h&i^w0^S3E*dF>#uMD*Nmi^8I&A0l4~LGTz4>ZN&`0!U8k1_7YKgZfMVg0(<~ZqV`* zWGD-5FLPLs{AZ_}KdJ5*yzE6G)8_BPqss7=I1A>ET-0k)#6tindgYJW#gAe@PxJ}& ziiV(>(&H`oam!JGGt#Nc;z~R|Q6}h%3mab1pD*@(&Q?8T^p;%#B?_)XOc=hZlrKc= z#=kekT&XXBNvQ_hb2pzQ;(2L`OGx>G0KukrJVg-i zs||&E$aReD#Kn(~SEs3T&g;U^TZqB{VHBd3*J3#P8>~Yu*t#PEWQm}QP0HQbX=aBe z+)lz$6%y1OG6(*`X1#_hoar7%75}S4h(&8Yw~0Fsd{ga{ZP85fF9h6n97RBWi3`!T z1ZYPKfeRUB^QHF97aEU6bXtK_%pMFo{itQn1W#bRT(Aa*MsnEWeGu>sS8xxq0U?PZ z9X?3GsN@x18ViE~1_wVtmUxV!ZKG;$m#4U}6z0obkUmb0+!5V7j>2TatKeQis?`CQ zEe(+z2O(MApm{Q|q)L%db5ftUjEQtoccS?$iNZ|r$OWqriUELE|Ne2SB+}7{<65)%tGwxg-fGE`ru>aSnZYq2g}g@+8p!8 zLX>Y2C}1BKJdDE^1<(c*=I4qpe@Ez8P9U?OJB+EBf%J^Nsio|ac?6y_C`(W>T>!;$ zLhK*pvPz*FDZmksT&-z{XUav{l075hyB$Q(`eYGsj(&2Hxe;Mg6gbyi<-XU;$13`3I?h|z3b3+f{vlh{ zGSG((;_`ha>=UiDFCs@0N@IlIDliL^mU$ZB8>csVMG3H$H7nPXoPKYmux%&OjfjI5 z>;t@$rXl|+LEv3w=ykpfd{JyaS)MD75UlaCS zTd$4r2*|RL!!pC<8_-BUTVu2DeWun1gwR<5^pV;QNP=ntG00Y9r_{3op_frQ-!)& z4=}c#m^moFRy}4_vh7A%even&!Bq!jHe<{}>j{jnRr&7^$KlHU~T zM>h~gqJ+$2sUH&ka1BPCtqzcgY1Jet70mxBqTX&gx2!@}t!H2%lv$hT z%1hGGOFvBqi*t4%tCm~S*+LaliN6ZgEpd<=v!s9={4+D$Ri(2DZHABCf)1!HbgS{W zlD|`RJ!3l$h}~i4Qb6PEyR}S8mgMOn`|t>Z@Hen6E(oV?rE<|UBTFQFk-?!tP;gMm zU?N8-UWw?ix&bD8q$K6B4}uW6=OC{7%=^3DIY!cSJ3qZpuqT0P3sU~lm7Cqa`UK$e zRUjkADN{4^>5s5BQ`5>_gU}~af&OwQn;z~U{-R!syp};H(mL5RAv~O-NlTb9oS=6y zROvmU5=rYXyZ*8b7jrHoO#)oYAjUUOVu7noVdV*L|JIGP?-mq_4mTFp6bO3}Xc!aT z@a}c4MK~vmiXQyVdlyoDPo=H{`jTb9IUK~HI>@|}n>pR#5|e(*?1+Xi-wV*b1@n-0 z7(&dbd`aX?1O3A}VJmp3^)v6vpXF1eX}Dww-2yts?=geBMub=}g23)C&$Ss{)VcnYEQ;2~but$7m&RO|#N(@uT2oU$-fO3h@gm)G32i z-NXaPC2SAG5{iip#YreqG7=So8aQ%RP@Ptg6Y{yk%a#x{T?qL9TL1$sWB#L!EllDAzk7v(?ncQ3+Y>(sbU?QNvoH(fbh@sCd^(f%)EGf6*TKT{ z4xt&O36P+?a+WPM^wJrFlQfNLRFr1RR~Foa<*nS*-TA!*Bl@1Gs&?FZh2aZjigKfC#9vs&;4dGpD&^I#$j$M^4X2)4%Xt^kCWZLQu$5zUR!%} z;QUtA%X+PYf>X1gou6yH8GfYl*Ub4M9W_HC37)J_8L8X1qoe!oBOhYjS$%`89}zQu z`l2h$EIa?w#_B=7L++`hv{>v$)seRb@So zt(9Ish`lAy*-@VWZF@aKmxEd-nOY;N*TqM6`c`^E|8mEA=`iHj;7_nh-Qz`|YBz7oG3@!678 z&Q6?1xC){W&f_cnY5P=&vuqn6KHqmcm;+j|mX{~^2B$bB)^s|OTmGg=>%YOlv%xHi zToteffvs-pjKq`<)zh?l&{WG1rxy)Bo=?&y&N)Q_kABzE)~BiQZz-y4X-`z{KHxt+ zLE;npXU338=)2MjD6%=KAUwJv(yVrCz;-fLhL656tpPL{U-u zMyYsuv^T*wb}>v-cqO&(3EG|Tf2oO=?EnxT6|Dl$4R^Wiu4zF3YY6Pz^JCHp33Bg# z)4lW?FW>vEy=K3T<_@2UrgsA{&tyOapRZ*3c{*Dh3OYYn(l^8(!2SVf4XUB=G9d>K zqD#R5FM;+~JffgVA!>NdV2%RmQ`OV%B*+Glj%v8J5|yGY;ruLuAwUb-vbkDPo_rt=d5YDqf8j%>uuzQ_ z0?4B`gXb|)nK6iX_?b($Ehj#jKS!%Z`7Cy3XGY#lXjcS z9QssvIjBg5kzk&!DR5NNGZQ(_!txmv#uv~f_rcd_VbD+`C8S`qXbRyXO_Z^+3OS(Y z6imiYNUa_()+){m4;&)4*K%d)+K>gTV@0`k8|b0dluk4czxhP z$NFea=fptiYeuntU0OPmlkGg%7tfC=ppIQFQ>Sk?;@lL`E>L+EkeE@!m8J~|6KEp? zD%JxK=zyD!^S77a`vu=odcY4(pr$C-buEXJiHLYbcCT=Ohf!rH*y2%_1UT zd)_ezER8jmt!Kh>Vu|J;YSac$Ut$mhi@#2CoQ6v*f1uj2E!R1t*Fp{IWLuZdroP43 ztUXE71p88ouSlI9gu@#L5d;qE4M3omsR~npxTfEH0BqT#lcVDLZd(axa+xoW6Xlk0 zCsjXzjue29}%)PmfZ`oyP>R+aWG`wovY#L9 z^RBmz2PoIP^_6UIywS1Q8;*269g~bVZT!p>0 zk)*ew#z9I?ps}fs>@-WzQeNC>rxw*m)1;fmf%a)?E46q&U(L?TzK;vLdFGAsb>pQ_ zlPIf$yj1#YV@q-VP3`$+st)fNMcr>EEW3>KBqjT*Sh1g?zDFEoL0Tnds?-nVtBdie zf&6w)@(+vX*!Gb32ezSWAAnCXG)*4@)G&jYG|u3^y=E>wEQ_x(Z;!4?d9({Yc9ZeU07{we+2)XXUOWzCyG1tR&mm zpwGajdKUa(Ki65G!ahcMdI8G_()4_7R~Si$`lx#Edu8trxw3IE0#0LraIZ0bhZRW;T-|K#tC0Or)2o{i=Vmr zA@S(($R9-0wjajGs6o2%Vu0I)BPNd_a>$gLnT3W>T6a@)if`EcS;ECX;<0jAL-IdL z!xk~rMhZR}l%C1?Dxu?FeKaI#edf6V`)h2#I9tpERQW#9CaVS>(RlCIc3A}g~oWtgN8ejfp3-lTM;+b}t8HME67 zK-0iXSDFbZwI~wVlcIePR86CoAWBRq{pSZSmtSl{$xKlH_cNzp@$o+{u?(cqA=0b)}$yW%kvOtdnWE7nPuvLxMWqxJrd#3)oj0w1T%Q9@`b^zxj$%Qslv(>cFH4AK@h?qpH&h5HAJ@>_TcP82z8@ z9^5|6;R*+0{q=#wFTra(fTlZnU>>@E;LkF?=B)RRA>@Cfn560%ed(be_L9CW;$2U{Di2nzr@SrsUD@F?7AQ)B@{>cVXx}2^oeTic9qqPVFs7}|)L!ak*GhbUT zYE%K#BZEejDu5TgayCGF{b1R>3s_f)$iX~#*^ixikpA{xQG5OyL|P`qY`DC{6^vu{ zkUB!B3a|U|&swv9|CYLxBM~hK3p^u-dOno^6jp$vi~j?iL!W|OpX)V9qq^AJ+NsvP_0L<6(6$-mq~=-U3rKigH-!z!7JczAy%O)vNOCvRoZ z^XTgv3 zj(@OX;l!8d9f2@Ohvst~P6RC^q2+Ib z%P`4ruLHP_PTj#Bcrfx%@C6FA1IgfT0Hw{~BzNec}e3` z*vnnH`9rda8O{wAs2S!5Xqr$w0wA>WNBK z6ifMl^{D&4gB_Y7-n=cs7nB@@N}-1exdsO+8$46p2T}v+vH1Za<4R8wR%lxeKs+7I zKwdNnN*pi;Ie7+YMZQA9&npq8+A5x`bwG~k_O1!WGr4i6CXsb)#THX+ti}3YvpJNk z0M$E)03M*rUWs@S(!uMoC@2x7w+Y+N9Um+u@%bSXq*T8WVbhue?d_1ATWp8>salic zEqKY#ppiQO*0YMr1OfpYd|HS464b@#w{4Cb<27Q znOxd+zf!&IG?og77%8F4Jy35J82vjfmUN(JHM;8D{bPiT5XJPN(8|kpBTHFj^TKqm ziAUgII};=J;?v1-5lh&2d1wCE9V?>1e5(W-n&7XHgx-F*1I8{ESj+{#u^U9EcdK@m z{n9e2*?~fJameiAo!plzX&n-LMLVSrDIhkac0VxWo`MSW)7kZXlrT*Tr0G{xqD>!% zgN>l-{P^mBOs0g|vhEL3t#*xXm-TQ$%brY)o-=Nu){>=ziRs+=2nCd4YGWw8Ge!nQ z*xN1s^j`^7vJCnJl>p2478b#~{|QNK0WV{@<`FJV&_DEbat+Y30z^{eaV)Zu!nf=L z&L^bQgV)QBvdce8I>4H5UCN`lAZ6n*t@Ism+W2dL80o}Rr2atX8*H{sB7I!lR0UH83HH_ryc)Ry+$z ztuj*6@kg~}^5D-8)Gml`Z3M+j%5zk+DX}_c80CnOnT(3{eneFx?))i7pn|Erq}|S& zYviaBvZ7xb3ecj;jcG@zsdU>g5;n=Bhx!$*>^-j|x)gfWXms$dcWLM!R@K-5Dz+dvZ)!2vp9m%pSqA0Uz#VS*m@tv{JiCBG-oyVI~WD?(jDH&Sc+>Qnb8b2(u7SKPw z;$5@{x^pZl1Va!X;?1ZHNo6S3oE87Q8YUryA22vuJuk$Bc*n$~d((apCBCxz`L@6zeS> zvJKfh*+?y83C@JBR)4wE_k}$o8rckh=&tu}fR%kL@6Bn#^eGvkLBk!I<4B6Q3-DMT za1h-Y`nQPYA+OB1X7{IKqq#M}cgKFI)T~!c$NJ5I$liuIV(oPGFvvjCTsbJIQcTg^ zBa`a0r3(95`_br!qEVfpBMXeGeW6bmCtGSgAxn3hLTpue0QOkw^a@YDH<|+;A>aM? zRwK%FeMK)&2nQ+QMl*#2eio#F^h2Q|sbx{Gh30qwWgB5?KBKTBG5)s36@c?B)vf`w zqhAJhv2OkHbJo|7JR*2SKq)jbyoGfECxg|-Q}V&R{7yw16IFvqt$E%<>u`(xJaopt z1WaP3Pnv&z0#e1Sh||!^RFWIdzopRdH;Q+{-jGoOY1M_y2VX938KdCW!R5S)ks=9w zvgB{S)GPg9Jl{BC)S-0?y+^N40$4TAXPQ#wHWAB($ty7$TcV+J{Vev2}~iQ z#E|r6yzET_K+OZv;#Gv=J&6yo_`~0|UFPJ-sT`Sba$gxNb|OsD0=D8EmY|X8MfVtV zH~j#W&Ng%um}{inihD-d!r0Xeybwrp--S;ZyP7~^oqUV*C!~XVYQBZm=|=ffGl)fe z2P~+l)ewa@VF7`iFNj1LYL|y0eoA|KOOwBKn{@9n<@*%9yj`s--pp+*GmFYCU_pYY zFrKg(oIEr5lz+WZ;!|GPft$4*z^)vZ=X&YOMDr1)6RC^V)j^YtlccQ)Rfd~OyL9B! zmHI`H4BL_S1jkDaBpm_uR7^|Ee5RR0+6=~ylIC|{7+iXNOMbz81KInr< z4wX0B0VNzCi<((hFM-r7K#1?~CT!|CP0(muwtzdC_l%uadq!dZ7dy-kUVD~&nuHAF z!R!|Pfnp~?e-6XfGv{fprTXJ*)aszgxw3`(*m= zOUy4p{2J3MtHrNUEj4pTKG{ES)u#@1;iL*!z7BW|8CpxnZ#%6_m+tFVeN%G~o*+m| zi`lA%18kvTYv~Z|tMYHZPMHS&9&_^(0+jMsCj!?~Z0DeCy)R?xx(T}DpYR+c(I>Ni ztx3yA*u?xJcNEs4t%k|UH(qO^moho;UM&7{J?WB?X?MC7?-{01(f+y8Q*HTUwTMO<1{fLBU>e^ux?KWaAg$F2Q zN+Q`0bnr*t@>1*f$mPbD#zcx&cf@;qsJESzOLDcevYL*Zu@tnWZk2${7}%*k`dWq2 zzviN<`h9ILBw|i;T{@lLx#U-v7D|*QdX{Fb7}vJq)Ar*uiwYIGoi5bUV5NWFic&m! zD2xO--REr;fs7$Zr2P(+bG~2QS~!u{lbxYVP=DrUQnaO#=#m$yJ4)>{m;S=M^{60F zQOC9yt#BVImLO9iVr>Q+jz;Fm@D~OeK?(vx-_-Slc4@GWPxR`&5LUUxRRO8%Lmbtb zjdXgBHOR?H=O~nSXn^JA15W)@?~&H4<(w(2+(7?z1YkX%V^TW3OXP9cKiR@M|R$-Hxv`vJ=WEXq5@oF;Kb6f^y>#EU})SLOu$UMMvRLlUU{gq?GAyA8>`UBGzdi&AwaOYhc$`55r zr`975#ut-hVkp-nko+JiH<^v)L4nugDG{{w8duFs+{scXz8R5ee5K8Lrf* zSEm#wyQ%&pk6yS9%@Pz&s?P`2bYVPp?Qwac8Ywj}1_~y2gQf_aDfgZ zf98)4L(3k-8v(vofxneAK{65m{Qev06#Dh(1*Yi=<8?-Ra{dxgY|s^gD)l~^$WcNl zpo;P3Xy{dkVhdsdTKSubRoTHvECJBKAun}F?ooB5Te&-G6W!*%j(1Ev-U1M_plSdR zkKK{FjuF)V^d=YJClz^@fo=h4!47WY{R1`R&xBDUYMs;=RLt@3zv)2#S(~qajvjq_ zFfIPSyXW&RjQFE6beV@`ioK z?WKjLMnlWbGJ59k=`M3ar&xxX`qbMe8#|?qTARZ?6tG6ielb24!pTJX0be{2y`Eh;u(pU+n~RDbf@mp%Ty*^fE)^X5te&S&*U zKm;tat~_BE41nmL>-x-eOjgyy^wF;4H{OAndGoo~ZNmj^d#4OL>6&fu#^lHNCu?qC z`v(+fu?8DQc6xPrNKwiR+Jw7~P!v^Pe;z`RtrP%^(FM)^3Hjh3?S;nzd}ZJ=za)#k zSOXs|wjl9P^zRFUpKX8S@oHUK6~)!!t1TaWl2n$UN9_ldf+c_& zRp#8I9a|F@tVu0P0V>Cj}fA3qFw!+sEH&Y>gFzX&z_5IFe&^ue|(-WR?j>2#D&qd2I9EI`F! z5Bd1<-x7Ox@O+l$%U2X3G8ySGCsXS=-$qx0{swWuCJ+d$^k~5ag_$CYbUVKRNDZSI zn{PP|y`O&<+9-;)6Ts)oosZM94Dp*7LwM($C${Dy8KbD+dp>=B3puKQ-2LHfl2cFf z5eetR&&$R&nln4Dn-du&XGFiBkGT)+bkX02Spk%%3)*XU^Zxu4<_{2%8y9YZ(qd=~ za$vFCy~u=%r1O36FBl{1N70w)f`2NCJW_@4jPRg1uTc`uXkIfx~n<2G@MZk4(y@rxztWm(fDA z9UgvA*a}@)wDS?aLJtM+s!nu|Tl|sDpqZl%j}iUsw+P%D(wyqt%(K)S(FGx&(t0n!_-Le)X1{JYp11{hD}9 zbkc*6ak~5Ilsg#GEP$h`iP%d1qz9`GGOfQDtrXinLG5c9Q;kSy?r;b!9Fl@FDM$g# zyWTP13Edt(ZJ5*$sDR`Cuu;m&#uoO6=4`h$mp~Mmk84VzHz6iY4<;F1&6wqVeEoF2 z;TW{$nD<6@X#IxR19#|oB^h#|R8FS8sFylUCc&fr9W{8bwq@Ca+dysB=ZzF#C1#90 zLaULfFj@71NkCaymp$EzmH-W<^Y;FYiErt%k{l53LQ>E;W|7}b}W*)2SX) zzT^{=!n^F4pT(x^Jzz;I4J?8VFFAyFdw}$yiQxvJhdG#QxFe+A1hYH0A<(KtORi$a zWOWhkET^WCkU-{mN(&+*9cxqJ6O&0Zf(F$GdK6I%!XuoxP;;wMkoQ;dE{$8sLDuK? z25s8xaE3phNU4&xX3(G2Iv#&l7aU3>cPj7ESm;Gh@0`g=L{E<}nvRK>7hY!A=W0~# z^}C&@N);Oyr?;@+Vffy-d*CX|V1uZ$-Owk3iJ^_z3vqKVvG(MaTtdPp&;o@_K1!UH zS!1XyO>o_??fU4;Lu%&wD7T|9@6xS2$gK)Cg12J4^E`T*XYl^ zk=Do)j(221U8`5W$d&W+hzZ>u4wwkZ>l;DW9&r;JN6P6DO z7R7xB)u#ZZIahpJvp6oO@x;Moz0S&@HIle62HdLDS)uNSeq4p0WE@*UupBIb1w#)(!Gi(gvU!uNNZ7`0Wvnm2+j_~eY#sJy#|lK}{q~8p zSbGrf_TB+p7u?EHgcuL645X7hd<#=|sxpyo2Sq|Wj`mSXId;Q;`x=GVw>7n?oar|= z%9Lu)*O1sw#|}+^-TW>9ZV?qAflrH!%NHbispgdO_-i-_6r&xQs#k1=`>qGK$s36Y z+0o!awcMY*RTTcbHt2t?cU&jcLL+1YDWY)CgzRXOPWUmFCW+1O{oareU|O+}Xx)<4 zoaCekHT4hUf`^Wc0dXAFh2dCBw2HSYS*QNB>*Uq4aU9)TNpuy5Eu&`Z*e{FWe82CH zhhIDWx|*h4P+H;qb<6Cq24$+CgqiIo9CSl54>9f$*lLa6L|R_FOoJ@q+XUeD-369kCh;44RmJ{t?ku6vk>^JVU_Sj!6)UMushXDeP^x(Ik{ne z_8q=gJY*5fEULMN+P=@@<5Y%=emBo4T+h8Ccxrzt!3&mA{HR2+bp4{;IhXPLo9jcp zRf9?u7nO}Of;I$9IwWVib6<%tbl=8_XiZIKcsk3ll-qmpgo$o4-O=ncosv!B#w6}& zUb$s@|0+$8qMJ@8M_)0Ql=VUBNa~mpDrqgjx6ce|R8uyN9S2>xB80P79 zJA7xIt5fC9edjOUsVDr4Yz!rGw*``pYeP+c^Ii8Af;o}w1!_4ob=8H@a(jgIp zfg*=5JcQ#XLB{)82sD_PBIyd%v3#8%Dja#d1)bfR zbFPUTxPBG4*y0^mbR8 zhQs#3!#%liXsGhmZ(RN(h6vX0C4mHyFhrZ~&d_eq0ZjBNTh=rKA}}sPeAN4}h<}bw zY^P4`&*;oui(f>M5erQEnxMMR01HkH7yPlqC<$vrItTMY>Hi~2uC@3Ad;OH;h^$HJ3bL3f$YX0bK z2+{`o_N#<_2-Sw<528d_t&`#|#V9do9r`muRbL1WvlW5C2nRej_(#$2d@e()g@U(q zOD`3(4?|}*SQv2G1XdU1qSKKP(#C=gan=+-hc;gTnv7W(CC`A0izU$HbKn_!I465S zm2*m7iw~)1z-IaC2+;hc_PCSsx;DwbqaM`~o0pRe0-}l5aeXg|z2 z4r?;$Y}IyvRtgE#ANk23S^D#FEwCD+Rdj#m9eGeMJR>`C_q;|XS)z=ThT0RZv=Qh6 zb+&P;_-slD9=_ri`F^nGY^0e49&p}S@*xxVdd zAq3!q8;Lw|+-PbQ9_$ih11&H_-UroZ@T}IUDL{4#&Sw_K8VK!k0nqm8It!*oA?67O zdzbm$b~Yh(3n?zC4 zMf*?0O0Ocd`=sF}+Khy=NL%C|w~BK7LF}NN3U1zqp!1Nfx!BG;oA6H0H^a1{f>w&_ zX;s_D7e|NejTv@b9AJic5E-$vyb4~>md15NB@fNwfA901im$bUHAtmfjy#)<%L~Y- z(^Ek(*t!DaUgP{a@30RnU&{~Y`K6O0vnoD*Spo#GLq_b6f2-{gI#&D?-GI@z4-hL= zQ~F#5Eq$#sCk=$?57y8acc>Wvi(!M;fHq zu6#JH45}So80*E8n^GBi(E1oq%H<@X=wfnu05u){qKUA#RsV1o@M- zpfR#Q!W|R^mu(F`;9})gBdgvWv}zA~s|~jOAXChs(b4JY>Oc}bi9)KF8ANQMHUo>6 zYL;OewqHGhU5GXU?yCg`Wi$n3gC?LJnQy8C@OyvJJ87_m1gtGLX|=tI0v#>g9=}4| zi#=pElq~inD$qN__?DODuZ^|It00G9@V0mB`xFY5&s_8fi8M1c4 zwV=JI$BjiBPLSDP&*V1~QT}I2ovoKY#B9N8i?7O;l)PJu)KYs^VCv0KNs#5B_>%>Z z1-7?;QSI%6RDlyjzG@eec{^gBKR^^L?iq?MJRB(Kl?gM{fO;re$4Tc#bZ>5)m;*>T zdw)480bTrkhYeakM0W)~D0hMO&}S1YrjB07&04KXUAb$Gb}DdFqGc%Fco-8eyv$Cg zFWd0650)O4C*p?O5RVVnHP_k{DDUZlwf?8%hKY%!prNi7|Dk<>i6twU$D4*R0c`)b zJHSVV_v8r_K3#I4JBZEClASqGLRLX2W#A6kg1M{$V#s@+=!ek+fANa?&nwb{3o z`vrRfI2+(X|SES_2kWVRKt{r~)g`CDDTThgoCV$ap zB|=S|SWitrG||SCPjmq`+Kd$*T-i#*dy&n`E@*ANzG!HKsZRNjy911KY5P=9%~%ex zuGCGt6UiYribw}Sea}i$O*>9d@zyav-6BfGe-leSrFtvjf!v2PmyW4lU~X4_v8E}G zX~3`f;o`KsXErt=up14PA6Ki2VK8i7RF6|+ky@fAsFvuFSCMT$ z!{bwW6YW-mqZix-o5z$HgE=t;r-qMEs96%r;VV*_Cb$10VK(%rEAvuG%{8bXvc`Wo zJ!VA|j-|0Y57U2~XI(90jQ>wj+NKb)E@@8z{}#dEitD(?V~d+}BSJWuu9W|$u`3UU z`dj0OvixkrkY9-GgV7J+TEoaPvW~Q%6d{xmk~K@lShHuZNrp*CVyrjWQW;w{$%q*j zgGiAj_fF_dfTz^XEMCJ>PTQ^PV&3yzl4zd@3+}`NZbmT0ha%I3;mTAg8WX z5`VNELksBSMgCf@)kpHV-9+1u%bq1Fe)1h!2T_UO@$fk6J@VI~;4ZHZ zgR7o+hLwdP`tzV8mzyLmWwfK4w|!h5_l0W?V_WeODv;N@@>bEg|Kae0{lkZC{)`|TY@$raqA3%4fc3;()&JC+4~pxTeKmb-d73mg-2 zW$IzVor`csW2fxv2Zt|f^1ZVmInWV8PIibkck2hQL{4xr0#u4`5jczKrjMdF#k{W_ z)D}3q(+Z(hd~aA*5SrMXG$uCp>ucvY>r%Q5MEsqzg6oy}ND1Ov<%=?UW+jDML<}Rz zgjqgsX|70mW$!nEDFd2Xq^G^UX2C<(ygtHL3Sip+6rx0pE1luN)Hu?q_=YOqW?n@) zenuhaAVEU;i*y4I`~zc~-(m>H;jDIuO~pKT!$_JOc$uGr`V9oGWM5p&n z185KUYv=BHsZO3rj0>q_t_TouG}o@xHX9yYaaHFei?R~pLfL3ur;ly_!fe1!6N)U zVNgGY;tc^nuMm&P=-Z!E1sm9N_t1vxWLK53M6EicZ(fSJf1QHcUfz`5q#eGZz3U3?nFMP1sCNnF@e?@=GLy`?qa(9Xo1 zIr2x{9Oev0`$LC=nN+-;v5X7$$B~a2fry7>z-ko}8(^}f5v!J?NAfSC%z(4-4c0p) zO!3$Q3s#3LY}`@rlB8a{YqRkh%X4M(r|ddbRasKayleUKUy6`5I*`jzsL8M zUF=^tZW~G}ZbkM1sZXaT6`qrZt@2ey_cL!+t_=&7PQIz^-Z=6+$V6??)I3cb=v&rS z7p)~Nz7YMb0e|h%oAA_imKu#OVv@-uHR++!k`!w4*0*ll736}Dp_2%Gyi}`y>T4+P zi-DY!=zdQ6&&ZdfB05jmz6eRCtLgh)YLKHFj_S`)`O0O zvC1-m?bFc|=T}pLCZ~}TQChD0$OYqN&tB_8jwXUY?Fo0UYh_tCz^W1o883D@8u!YZ zh_I$1gvW9ZyG#bTV-6%|&Z{qTbUAl=cUoO%A(dARfcuimazD}H(U zv!K1cwvm+aa{z28`y9cQ0p(Tnyi~p7FN}S?tGPaD=oupeW4C#qHLKw9G}XIhfqJZX zm(`LI9Yfy{{%Ml`8;}5S8Y`$8L~lAm8SK6RA(>3m7r0YB~?}XW+sE(C!i(fm-HxA`@djP^1NA-k%(_Vh{=;iM{ z?w?TmaCuxKnZ@4ctb%oyo~^{$Tsg1#alXf2&nQ5To@4rxzBX{g;g8C1h-oVw=0Ebt zr`)o>FV85PiflR6XUMM1mpsgOOwi3pS39S{rMflnLn*}(KPY~?;Yt12^qt@{ezqA5 zyXj}O|4}Ys+`nIzn%#SOU%k+pSM?;C#ox!r_p#db%*VoR5ElRtFfZT*RSc&HL|uum z2X*q4jgCV%dlC@oGhNv1MIJts=P)$=82LYv*vQhADzfby=0q`D~!QSsAd6 zi#G({$QF9E*72QI^~#HcOR`LUx4cGv#D(v`llmeP#S z9~o>)&KohT5dXo0sUdf8l3fY}kj5o*ZctV;JEQhLidVMmV-40m$lNUetld*CBe8&8 zi#&O@DbVwVnD(C{+=0{P+`<5Oy9WXllSn_rSv!{icpNea@twYPlOR$Sx&aAC466Cz zJ@7%h^lkmQZ5cdZ8IUX9L5E5%rgH{g(K z`JywJ6rm5L8|7@>4<`#j*a(s0vAaqWX)nfplG0D%d2us4-vH%BDVmG=nXUl?MJci`qGESAj65^|k(GApjwK+V5WbLH?&xXRB*d2&rN5;9 zuA@}VD%>DwdjgA9U%z<4p7ShB^ zqO2h561q5g$gi0K+6LkdJ34vTl?37@R!x7Y8z|gn98*T3x;eCw52olohE)lszAm@S zg3gA9(IA2|fMu;qkmXKI*;>F(b&CLO#3gywC#AA=`P>q4mi>iV0^ojc`$&(^C#3UKz-MrY9O&@HY+iI9R zIDuD5<6|$z4)E#?Pm>0EJ(bp&&3%;dnOiqU4rU)77w`#1;en{`6kgu%U%~ zK>1&{UyeI1stC}v)4qF*bdGF?(jJPoNjkk<1OSYiX1B|ki$BBmnkCQC7ouor%@Rv! zV0MJbgExQ!wn%ELMvMb@7nC$#Z3ZZa8t;2aJOK~^JncK#2Rx#`G@R@ku&s+u2_>b)#tl&;t_djzB)|cKsn;41PNb-o9r!J58w`j#q%UWD0*3^qoL$LydrX z+?y2Hi73g zEFse-C-jhyi`_Uw^GPgBU~6;(OZ2KENu)3^pf%0EBzTju7&Oezo)68rp8yhH4LrA~k}4&2VStIM{Q1Pt*y( z+aL>h&F{4gftp1Uc@nYi8t>3$f#**DvVtm>jzA8Ysbw%5PN0sd> zl5F_TuTNFlm=eIC@L%`@I%{WM?7^LHr8?AmAI7Fr=Blc3= zWInS2^F@eQF$OuRFua1$h^ry0r+G9=Up?ysQp$ZMSfI7Sa&lIy>m-lzKU*S?LFOWc z6^d#<)`aLNDlsNr%~U~cRYcBB&~?2sSOsGSZ-ZXfWt8Xqx+mpc*-+`LuO(asOZc-B zrZ%a?U}WS~EObss3oDLr5&KLk*+5KlGfTxo4wxZKcO@4NT`=s5mMfow@T`Rh88&{Z zXe&F%g{vkf4xPcRG-|}t*gd{P6b(Lyhyy;EP9B)^FvTDmmB}#}iNF#N~Lx;d2 z1f-<9>#fbb-tX_d&-(}7`+Tn6%LVq?d#$i`) z%7TT3y^Dtn{*U$MpK9>0OOC3tkFfH)X&1p4IA+p{(pXqU;RGi}SHRc!cF(jOv9QRT zpg)&>nKHOxVV!5d9!smc8LUiPNuqr+`erjYi0L7ojqg-`5N(j9UEHT2F_DwEQ){H- z6B853Q+G(m^)E9ul^CYT4fl(6u63_<>ujC)EUqXhD_c7EDEv6pD5Vy((s~jx`1^&r zdXv%0NRd%zJde@NpT3yOJ+F6{ViZ|nkxUo=4DyzCoyqjx@a>MTAq=I?WbHcX|bKiyr-N)7ZrJqn=E(7MA>SdVS5 zWs#lHXqsqEng3&Nl-s!Jot50*h2bya6K2hRPU#n zjTCPDdc7V%V_U;>vf0Xj8R_S-#ZDZvDp8~oce4{LbN4)6EuS8NhZ7yI*ZGWd{=KZa z1lS3*4cP1H*(hb=VLeAh&suQh!0Po{v6}5}F`oN}OF0FB@|=}SrYdFDy89iZmlUxR zQ$4p}R6;g-;L0`UXUEgAx;FSSfrRZX&;H%5^d%4s>MpM1_Oi61&PzAKq|OfPM$NMV z+~*TmzFQ7+*8VEB93JUpFHq#`;HA-ZYt@m7k+TxA^ZT*|$(nua-{|Gs=b$ z^7V*29!#E}-SpUBqkEeeMCYPav5@k*IQzV8I*_Kts%xomo!)Dw&+hDSA*e_4m?M7x zJPoymu61c4*u%iJiR#u&Fj^VdFZoX;Q1Q$XP@-^-EF|Dw7lkJglHeVs6W1c+L+DBP>{4witeYexy zVHDUMnzPe&pP*EqGZ9*kKWWooqr#+R{NC|(3&RQ3`Xox*#@_`y&Nyy|A}XqThF#+>b-JUbH&4J-Lz?d7f+cr0dU{M?OCh*D*jeiNFOVWuQ` zI2*NTLx%lEQ_ud1mR-Y@88^=S4?c4-n!mT1OsKs6Kh#K-dm+{0ij2w$Asq&R=V{Qqc192 z1om*JTWp8y&Ck$o^q#G|Ko62jMi>>If4{?vpE8qs&< z`JGX>`|G{*z4E(oP*whgsc!788ywMoNP-97RpLFj+Gl2%@@&&4y^kM^+qcqfqTbz} z31-iyN=(ipDAsE~NjKLlespMeu z$8qWx%L;sXuvt26AV%vx`*D+Jtfb|ZWfO6P{1d*i^uGPY0Tw-<(_Nmzs-1rMR%WZ^ zev+)e3$^*(zaF7#@upbd>OX7I1;T*`D+nY4Rzg}~Zpr+vm69I%^ZtEC=>~95dkmK` zA-mFc*WX?x$&c*9KZ>Lkb$YeO(UhrSTeI1+(aPZCf4V;@C4Rh8GQHKo6~4?r>A7v9 z_A~55J4=e&U7MQ>Hwal$Jsnoqqt5vL7RxTn`Zt#zFmor&UXJF+=zJ~x_h$MEe!GlW z-<(f!>>lZ1^b-07zM2Mk@k7DD_%b-IG_@ee4#d+EG>_cU*V|vORk8@aM{=(oE~GM) zT;IlH^FCV4!jvpMsGN=D(fvq*45IhAuMX<}CRpdHKcBg6#w!kJ;VmDstz2SiS=4+! z;?Nj^1A9;r&sBHAdvdbfgDD|>`^k!ZESgu4T2`${aGCAj{p$)j`u!zLlnwV#NA4vr z>=GK>Pqo||2V*=1P~6jt6G06?Va!tL=8=~9@xE?5eX^}nj9$+;!RHoDKJjz69xKc1 zyo(Um4#3%IQ`IvHpfJut<>VI2S*h;s4jYCK_@1$wfh13*E`G9sf*Xdl(z)vGElKs+ z-oqpzp6o3TbD6%}N+A*)xt%|ALrvkMBK4yzrDWqhmV=kZRs83mS}=z7FtSJOlRuoW zD(U+D9Yl=6+=294+-4H8vVdW{uatYQ{~{X;(ZhO#Jkb^f?tPZndI;87+`u`t`LR0$ z6}0AhMrkRipb1V?&Bf}rgs@3Ji%5eiOd!a^jGbcZH9P}bIR&-Bmzs%$#<_7h@a6pK zf@mF{C53UcG5DMm$-OC3S?Eqi;j<)>x=c6^Q&F9Ocs72ylOCmXO>C_KF8C7%N1jA{ zqdvZ+2YwWsWE4o}qTeoiHnn z+TWz~-N19R85|x^xN?ZLo@Xg^cyxtg-CKU9f7C=4|2WYI6{z@XvM_*J#8koU&#CWp z43`w~`ss$X+j>V2>Yd;n1*zs}qj}b>YXk~XYFajXl_=yk2dyZ^Cz1IQ&NS7lwdhRQ zc5a3L2V(3`5Au($Tu2eKsy&>?#D7ZxfoS*pJxlD3SpY~T8`aemVz3V!Uzw>#)0t||B}#-EL} zt`UD}4eM(8A5zVe;)eAKT)C&l5S^zTg0JL#FtBg5+R=@tN$AE*qb3yhh>zmzzZZ)fjAm}BNA!6PsN%azbtwFyazWt7-a_i2HjL@uEgfq9?5C4POM_D)GK^YQYsR9>9UXHd7B%&G0 zwf-b|a#mm1VXbM}vt-(r@H()TeV15l!p&T8-gemf$7?Nm4I=_c1^r zX&AoU|4}+&4ecmmF^=5t{c@O**gOm$OX}I|>B{p74#91!>0kOJ*GimHMQPN2GOpJ} zNwC#{unqv&Ti8^go2Qi)qxBc}G6}F?M@>{Y6M&ai3YV-$2bo}&B7&>Bd@CM@ zI=YqCQ6b(e#l4v4fnmv27Q^$S?UmUu@X*q1oUMB_TTpx8^miA+4 zLPTs$<282wVT0EXl0a5ATFi(G8{mG>R``1MqpUGQygWzIW4*Oe%L2L-P*e{@wY9oN4Cupn9d)sD;|B zGo{qC>sRiwu^HWUZ+b!g*L&p{4+ZkfMNxOR)101S9&(Ne$8NjU?sI~-wa21XE^{JA zBVRva*k33Plp4)EbOUMzP5_D;XtBSo^=!}+R3H+TByOW>JSDPRC{*CzxMXy$B9FuY z3`BuVp&+c#8!~m-^47H z9hZ6Xa4qN7<*2VVwR4ZSHvzg1$!>t~@`!QBgGM!F35v_I?vp;}UI2s;{NBM~#8>LS zv}{woO3ApRrYP{D;?L)h#&;h1T$i4zI>W}guF8UEckGei5!(hw_yZ=MV}I%`NtiEe z95e|$-0eqw=4=JzcK0FxJT3?XP?}GP<-h2RkpU5x^_7`#-EV=Oz}9nDyJEM_3x#&< zVmRY#6`u}EW=1I3I2>XGaG9S^cy^el1yBZShh-(Z=un9`AWUA@OP!xM3O;$KnC}hX z+Qre2QkHZVbn#0tMY2L?p68*~NR6d_#N0@xV&V$MpQEFd{xt^&fcHi@d1c?WbhbdJ z7z6SVt(w`x}_tgVO1N1FBpD!!^{9mz{>tAVTFP+yF zeyu(pZx2Ta4jYgPR-NQVf;h6S4Gri-nP(*n5`qIMxv*JKcXq4xWUJ$#hSXPq_X5CJ zDZE=(Oo+puX$$1I0-%dREeQ0YN{n$oKLrJa5$GU8F_8hNyCEEriVyya4go!|=9()4 zw((}8-?}0N2lWON7#7B~{tRq_EO9D}bsYzXIu)s-Z&lRX2#(*)taH$P%~Z^e+13&5 zPq-ScR6EQkn1#*Ynf7-s16)d*%2H5!WMO4ddIJh&E%&(?6njApSqdngR#q<*WE}GW z=yO=vR<$t4CAxJ(NpvxNqm41#A2jEt@a6Rh*U7vUcubvmDwUnYD8TwNE`mZP_?SG2s+%Q;q7wfS=#^DieQ0!U@N?}R1 z@Xy9xtEI!lAXr{kfP;m4P(Ds}1o}T>sgn&Y=`yhTt&64!Cb5Npv#)^5|?^3l_yqE>pEZg8r5 z>wM1LLi0G~^;HjvKpO%9tLeQl+wfDfw~i5?@)rJSU{pK60>N^57fy^8GBnXC0)*Sz zMqw=-$j8I^`fyT*w?u;Px{9F<=BbcnW@>oIhGGV!j@1(BkQO}D4n$tF722^|goV~~ zqhWLH3~I$p13LK!6fn^M3!d&wck=aoxI~LBbiVI%ev=O?{(MkP860r2*dEU^(DP|+ z_IP|Wdf00QN?-Uup&l>6AJ;7a|K2Ye$&o)sGmagJo4-mhJ}U? zv4(+u|6l@-KeP@ab&P^pGdE8DAtNoW=sdO~JJm3h;t*8pS+%W8vT=tFG)G&_m799pxOcA-Qjuo)05oI#lq$v|z%pw zmR$9o+*W}F?fc_`XQy})CH%%Ek@&PZ#%#=FD=7|0jqUUw6yx_dG=z^Q6U9I2rGq9wKT56TJ6 zXvSgb%aCccvre5r^;ufo@Nim;4b8(iO=P|sFf3~B-aL)ekvtO5FdPCLDmx8%BiMoK zwP#1mD+x@n^T%a|kLob`RZi_G|D@CG(pS$LVBamr1Xrq7(9_Lc;e=Va)lalC7m@(n zc`)G^X17$O8+db1*MroR&vet*V8niUPc$A;u7^m}&zh zqPb%&$y8v zuVd{|L_$rQwD4Hv^H&0SLd%bRf&sRa*RrXcV_RsQ0jzejLsXn0=W=qP#NrPt#_eXK zAUX|^l-8ejrhb78R#B&An`tIhECo>`=tGLn2{Vmz7xW%DV%Z#q(V9cyaP@Ch^z14w zf6fm!P$UHoDH&TbmBvWbLa8v(rLSmsV_Bi1m9C7PxJbTvZ7$=ObYwST>GQWpQ>PF95wy(dMWvxhf31fmw#U28FmB{m!87@-*pC{PPx zV{QD0+llVn1tgLOpZ=81O4V(daB>+MP+!|OF*;1=*mAEINIrE3L13nKmM1ysd~2ra zJ`}O4mET7Ihw^?BaIOZJVY*Y|{>O&dUr)pU^1hG-jysO#6K&a!@5~4s^;H8nF|$3o zVZgTG4X$+{{-SeW--Pw+V^ax;Yuy;qwSAH8e+JMq+|D-SK^fj#Tq1N!tj)$$15boA zDAp~zI1~x$N%Vk%n+Dw7*CJjjb&qw>&=*lpKn=^@CjQx0lAQXUi4k|~?!B*1?P7MH zt-}x1J;*9x6l0+QSVUf*lihy5FWO3icWwc~tE+I#raAy{=KP6UwmZpXKQ(llgU`Sr z<+1T;oT*-`Vz&a-|H-5-=Zbt-m*{dXIVYf~pm-@{z@)My**zLTL@EBB85Q3ffu|{_ zN)|)ViK6AW1c#+3Lf zt=+@%ti|zJ55?3Hki)G99lw#z`Fphp#GKZbgu+yHI(aYNWN#~LBP<#E0BA5-)CKiWmxk_N}d@(-JtHHUMOy z<*Min5y)x}w z!?;d*&3O2(T;p|Eip+cXM5N&(0F!Kzwg6~o0j%{~usBb@+Jy-4_S&7s--szz)I9)> z+1_;TNs)l#(k{!s@pUgGv4!|FQ0$t_A6{7nLWgz&1@C&zcFRJ|Isg`-9m);5djbv0 z2D*T+oe}2vvD0r)d$~hF@nGo6@m9c1gRkRjCq)@#sh!1*^KS+=Uy2Sz?J6$U@4ek} z1tQH04bu`E^SZ)c_+wFJzSbNWde1SQ04WBR^hj3oPVs^y*&1vNzB8@m2Y=mmCumR$ zrjSV-GXOY(knKT*Hit;O&C3WM36kGbE1_;7Zz=3R%|AT9FU&eDkZ4UhlHXG!JH-#LmI6P@=!q4id%to$YsKt!WKTJ7tXC^lHH)wGm)TWv^rZC~4QazTk4=So0 zI(9{UtmGm{vDj-qm2EO3##t($*qFprf#NTpPyDe-dyiE7T(R zriVkaT8nex$}&n^+XwsWA#XwP5t7YrjbB*OA z{Vbk>kc)yH69s5`#b9*V{;$_uf-%qL_`l9F%d=kDvXD{pWQ};*e3zOV@H1|?(diDm zP|r<$A8PWFGDTV6Mb9^Hwco!l@C;dark*4P0=7s*i;dV^G}Io1q7ot7bh7KOL)i># zMXiFtLAvFZDo6yfr@?4oW2t`&qvm5)QX`B>$u5pVo3cH~{)#yL`jv@246Vo}X|A!h zkm?gQplW~IC(F>>3YacU!oUdghGRV9LQiC1qQ$rDM?g1%+l36z1JHUvPikjMi-Ob( zQP;JkAF86fmhA|+v92PCxo9;uc0~IdR>D{I;=;Iy=)#m-uH|}{sOB~gU#k{%?e40g zFoigSs~3TX(6y8~H1#P`*1m~mp>|NmDIu~VXs7{XxP+4O%Ov}sFWy9D??5`xIAAyI z>D8Civ=swwA7OoXscjA74v+phrET?U8Jo!)Q!jv(x`c^*1<^jvc=gX&yS=BVGU2c} zAJO&pTgD<8xY%3A3678m7;b{xozaRCdAxD$r-{moEJ>5E@kh~ECvf zPWWAgFd0hrN72flrYzjDo%V=k(}auMA0ZEA0ZrED8#sMY%WP?QvX?*A|+AV8F0{Wx3Ux z@l7kwd}gfEHsKgrAn7*ST$I;S(y-Mj+VtFLGOORnZpmYSqxIdR@E3aJ*z<0*@^x~f z2<<)ZgwZVAT5c#}saL{!&=u5E;hA8QYkdGTvfm5d*GBC-wNiHu` z1L{Ub0el#!{AzhB;I;zZl!{^D`VJfA!Cm?6!A#rbklb6vo?BbXokfffqh;&;tQDoF z#miDTR7g*rVa(?q2e?_R#X3Vs{Jba?kJwH@r0h2NBDl`GZ~}YJ_Qo!=?X7rI{DEWq zvlz0ZT+p13d~ryfD^kR1C-Wo2xfwjIMf&ExRaL@v=(bQA>$Ga(weEE@G`??4O*B4U zm;l9Q2Ad}JH_O8Zt?q_2VQN*Jg@nl8vqy==lVnFY3fjSkmN1Y=DW~US|J)mfKUW~xYRDr=9V|MWs=AS1#i+JCO!*;T0 zYnN9#^o{V~`E@M|atoZqSHG?gC<;wTVPC?h)?+33tl~|t{%oE-oIFhWnpUwlt8U~< zy1@^R=GM-j;OAxRCK`eiWz`!8^TUDr>@B4s#`+3%xR@BZnaskQ;J&>B0heUcpOXY_2oL1iJ=4WJp{f+T$e0{ zoe-O8yf6Ye!{nxH_`S4!-OSGf(M3^BJe%mugr_z9P*bKuMZd#Vr2BX@A`jL}vXXj3 zAs3dt{3MXkH^-l_bjhy^flG$Nsh-Q)?ZCQwf}mY6Q@e9n{UkNpqJ2o-alH`EO% ziN(;y<4}aKx=EXGQp`C&86s3+0;9Cp9ewmN`A>DowWr9)FYN+IA}0ASwHPZz zUxu7l*+=xG@mIHWvf}s?ajlzdY-+fc-nR$t!eXk_Z!iEtBL<_r!d@1lz=+&SXRT08 zoV2o7aSY?47={!j_CyONl}CFPaAORP!^11C7FDHG2Fet>ID2yVXaRvR9+LztN^Rkt zfM)}V0JUgv7_#PM2}buVu?@9nGSQH#N5+wHg99|=yV7lJl1NzRk7b!{QdWspf!3ci zNuf0q%WQOCpuJ!iFd#ba`u78Qll{6@a+ZqC6E81Nk6|C_a8T|jU*m((s5uL@%$8V~ ztL_8+VOR<+>?H-U3--6dEa6xBB2|%P-Ikr!pTf;-uz%}Kd5zOP9%9F|e;QcM z;lD4Fh?DL+%Y0;w!H%Tm3Y;HQMXSJ*_YWP*fMTS0%iq#QudaXLs!+3f+|S%0-=2F% z7Bzs(gX6kf8*!8{8uwVvyO|hl6N=u{m%TXVv7Mkx(g+~D%(g0RXv=zB#Q8Nkv!`q@ z`W8lI=TKd)MdQwqr3YXjXW+$#cuuO?a^zNk0CduuJVNNHn5Xc{nXi>pIm3U|o$l%G z<+AbitEzltUcuv!%+ncosDYqAb^b^p_Y@6eoSW=#q%#(Q-l2n$GLVbOdX|(lAa@;}w zwI0?V66=aGi7D<$yw>pRMg)Q`$5M_uV~<3Su6X3uHz1y1zK|wTdjat^ICk}c2 z_H$9W?&~7usByipS~4{98+TUUxu6Uy%J$)V(-8UehRRKnmE? zZZisxMXJ0{#MW1Td~kYiq0C;X1jWM;gqf-BhUi>FE7r1V4wY(=e~$j? zGyvl{{4ivEdVT8zK)0@xpN6&X^{}(`f(SaCr+dc}S_6;{G!^!5rkJ#&%oF(M(7RU; zosB#tu@Yooiujx?`ta+ERXk@j;n}K0?|vp-Fs;SM9R0s6Fycz@y3r$3tcK7=LQZTy zgx61hbRED}b;Wmgz)5@8P+o<2+b3)A$n-LWAAWd(p;xh3_RA!og#3nM3n6SiE`Drv zM5g9)9z1zsZJ`?LEWFu74mYv5Qx+Gj#mi3a$9HHA`x*^36(wc@`%)SeQpiVVZoPW1 zBwq(um4j|PM=7R7{n~JbxJtWxRBETfuF2UPLTRIX5aCbubj`G469;7acX;`oOWPmA`M}%5eA1{ zt_#8LO8xDkOIx5Z9?wdX?*c^FH=AmkSC zR8lF<5J>BEhwWK5Ruy+2Iwoy@0=nq*Ot@5c%gF$!Inff=rZeIUf-j-Pi!TGC#U|i> z`^;7$Aj(i82{e0;J_m(Lgf1>2RYYjESpH#X-?}y2`tqfzr6HkI=V!Nh1on|!$5vcI z_bE~gb6Z1&eo-C2z+FICm|RLCV13nAIt?VyTnEm`3`pPA{57RwxOdaK86F8D17<#pR^##t|azy&rC{+X`s)VjcWvg;wzvrlqt8o zG+PeYKC{Oc_$_tho~!|Itah(@2k2+SKqCx0=JZ)n-J_$Jq+QO`7%TeijD7HFD|xpL z(5J>CFRLb8#va%hvfdBbc@AT+GnWGVH03l9Nb{}s;!htYuv2(_&fJonir&Ql$_PcF zsdv4Dec|>nHd=g4^P59-+7TOsMPnOknb#g*0pdihf~Mpui#&?ONtr+-`PNy7-0)dmzV_ll~mv zJ8$>Od|ndtxb#)J8zpHp!3x6j$>__&zh7wTmu^*cRzjq0t7$BW$ZUk@)uvb9gaj7b zc``gVMbKsHHwVAvw2b10(Jd!PEl@*>P9acL)noN}YtWW_p#{Hscc+_X~B^1lWKjjw>GGW8X&I z`Dwwgm_Zy%Ad2Z?{Arh;J|zZ`!{!wZj7DtInU8SD@g8OdJI!wbd9MkrcobO!oN+U? zjPVbft?8+61Fpw)oIW!nau1Y?(BoL=&)D%(HuMQd);A4jw~zgIGpO5CFKZJO0g=1~ zJ?j5~xh%%lIW02D+~U#3-4_NWd5D}sq72iH>+ilqBCk!|sK^vSfym0*8nLIX=gBmd z++7%swh+_EC2v^0q5kP}qJkv)(!ljkY5mnV_(Pt(4DX!y&LAw9tw750xj30upAF5f z?ZZkQ=FX#hr1GW4fjHCh(pY_^K`@As!23{)pZrLLHxQ6xPp(5tlaMMYdnjn5>$$4ekCsCXac(fVYiHVdIP(08I-M91N z2yzO2w(#@}3IpKaXnsh0{3BnevA4-uQY?I4`HRdpun=;+itsJ$Y%9`w5)tpZw5rY#VZm zA)#2ridbZBFt35<)3O0v)Ytgcv<=m7k4`99C!`QwdwXq5+1IQ z?$5%vRj%aV< zhF#zOtq0RaIycm&Z>4y_3I(jMjx4O06{q2U%Oorsjs8L?@VFA-YmS!IOF-ImOpSo+1*X zo+wp58-BJ&vLJDsrRQZ`%z>SOpf9OiG20W;GV5k3RMN=2Hk5{9BC`hia2xGwWFK6orh8_ zDTUZ(J4jNglT!7BIx_xm4F81#elgix;L8pwF&M{O^>HB9W!LI~VX`icOy7kc9=qsF zKTU zPnfV^mN)@a%Be-5Fv@x=oqy){{l~MNzEz~HnH^K8tqF^~6*x5u{OIHcz!5OwdizuX zGUL=feYph`|IpNuPYlvW^T$0tXXL5!7j)mhpWn~40L(b}kbDGXr{COmQ}yV2L^!>~ zqw}*)6S2VeJNW%B(X?!Oa>J1OlM(db%A<2SLnR{ExdA zWi{QQ_`m!6$K5kH3e58V$a&!J|No7lyy64%9lGGK~No;;y# z38SNF`9MwnG@M>vi`0CtKjl+7Cc$7p+O0S_AUlGbu$#=q)hkH(Uuw69B(9%wHG=sg28tDUR1? zEB~`rRRG6XlNQ96vIp5rR5jP(unzP>ibLLG%WF!-DTpV<2EYn`4HZN}0!3TARdM?x z;CP*>pHWH{HCd1Nd!;#UhuJnQuAT^bWuE36Y4UNLJZ`X0#Uds5$4q_hWpk)v#eAB5 zcb&1(w(gYD8}Mh`z)RfzE>#UB}85XF%(1QA9-LB64X&RtkCb&Rboej z!xN(@X&Gs%hp*5LQZOdxzaOsLS;6oLF3Y`%^zf`QgEI9`IbYaOJuMiks@e7iXe1d6U;fj@G03`M+OqA;Gahm^bZua%9rmE12 zNQ=i!5z@>w*5Mj5I@p+=2KEIaH3gn0@sJ~n_3!hj%0r2ud8Hj_M@NeA)rmIRpVJ_U3ishq%++zQi;T7%ngQ0R zYhZi`9|+-Ie*jA=81VNaEMQ+d&VdiWSYI+BnoiUS4+N-nNWISM7KrA-Q{)-P4{q2%NeU z6n8w&mV1oe=JXI3c<-7Emf08_{+=n^{CSEpt2?1xV97R5|Ii&R-L6lOESk{F@$a&$ z%3oY&aCu?*F!50dE(_*ynd59c&vfBcTOz}=y$=7ION*$~Iucn4PgyE**IEBVWwuwU z+rXYh1Wm16n0bLGi(#!|ChXt@D2?5jk+&FJb^bfHv3ZpsNQ4}V@A}(QP)ui*8xZ&S z>=_9b8>O5%*;RN=y%ChPhC$O8C9Mzd;uFv^*^(p>~;puD3`-z`Z>beSzP{@18`m*Z}Pb_!77XH4% z;-4CL3hZ!pC5i%yZm;6rJ{k^7el#X%{RqB00TZi%rho{qm4R^~$UMk%A13w#P;AnW zW{+B{UZ>a4G74Cs3%%H5X!uOwhXjys9)Sc?qRGz#yBRcCz=$a}pK>oS_)*N7sN|je zG>n!ykeKcknyU9T`j(w}4HD+MYRVwv{VuvU9(m6(^3{D*#pb!h z$=Ro3T;|PYTd5#fNjITxsRudZcx`&F6VB6sZwsc53YR>3B@8kL$_I1`g}}5Q2u&+M zgCL>w@xTPZ*a+NiWSO8ryc}hrk#zIFMRI->=5fkQqSW$o`ry1JGzSmf8cGoEEo|3F zVAA55Ak|@%HutL(n3jp5`K1vsUWEek65SVcS3s@+cC@M^@BdQN^1$Hkv0|zS?33Ne z(=ZdNn~hTpwOt1Hx#l}gw3RB4QxT_-&fc3L9~aMxfo9uckejuT=Dq@&xC@i8VtqdF zL0?SuUD!Q;;%MqSzt94lWFzo-Q{)38e#GbAKmjnqOapUKHphJkr)hcZ{+w}wY=B9D z`#|?po(AC;mXHX|_9O`&0x!S}FXUSmK7C4KeIo_9ZAUasJh|B!L=l6s0JL57|t{&%E|0gdjeD)A?_rVp2Q-d&JAk7sl{3 zobIMKr(;w;{C&Z=^mG$mDMU4b z+oT6(|76JE(zH40tt+4+&)}VvhW05V~1GJZO0$_-8_xwTH0Zn5W_eRuP=mdc|F-~YM2cy0#`*aa94RQjT?*?eR zg8-Hlu{jnP)*~Ob1Y=)B(1ecgY=n&QLuY6b4e$!~dp7@j$WA1`FzijlLkd*9J$Yc- zms?pPs`Fx|dha@JJMwZ0z0OMm9w-XPKmrZs_11bFTUmACjRJ3t36DHv-y{Mvoc1d@ zk)LJ&7e)ph0jheqL=^ZOo;^kwRuM2k8Uc77BK;Veec9x?)DN0to;?8(XtvND8YWD0 zToY{vcTnH2N8d7OW8R68VO9Dlbz zgSRTS4I(P%f|Votguzs90QitPxlFj_^W64fhiuL^*v76uxzanuK}uqQ-H(59Ol10d z*(ft5G8U$1&zKoeyd~XI(*eBjTJl(FpD6NJT}}j7KCo&{gGv&f;FEz+j^sH6G+7fz zaH2ZtG#rG~KMSH2GGSH285@nwKsTZcTpcmz()JFD81YUTH`kB7vqo zAaaKA8YBME%K9TfT zuC^OZaSgie6WZPKoj%HWnd(Tt$UNS;r)5+V*AQ-gKU=6gtzQBJZXyABVVCPj9x&7*+I2 zZ@%>_*_XUyX>%hPbYd=qz^7`}`KSg|xkfX+fwbEVkS>~Aan9q{KJazFYe1n$q{K~4egl2u8dTY6tiL~xk)*|cECHn-dobKS z;}H?#22A`-XY`={{5-hTw&DpavyDf~1q_$pW!K3K?E*i~`{jo|;klRBSsWb!1c~WD z9Dwh`UH(9F_kzgF`ZsnUw>Q@_k0CP^m!DkfF1S2$6-T82(0EkoSC#=)S`ct{dfe)4 z%#h8GbGbE?Wq-=vL8jt{6Qk>2?$0fE{t zM-A+~d9V{=`<~&=>w{5Qo{DELH-NrLaC)>$z>@5w3Jov9H*CT4h7CB}hAiP!A5dTd zpMe;#Iq?$}K+vk2$~tjCDdML3=_VKds}-UMdG!on&LxgCK?A|I(RSL z4xH!wrjBHf?{Vw0@p3>MqcCYSf`Nw%yA<-pKqJv5tQn(3r(TcuzB(W6l}tAN0BVKA z-^nub{(eMPm0xZ<4+xa!aQ4QHJ~%3svBf`)vE`gjMDRq|>6P%=dv;Vf%DXEwzuLTd z4^K9)Of5cNx18HO%Oy>B!Nq8+dliMC8w~)SVE?_<(ZI6Mn>kiL+dLUnVB{s52JR+= zHQ!9yh0;V>g_f%(J};Pt>lBFGOp&B@JdMTh{TI{*jsnZ0vk6gFq?aBcwX7%0Ru71* z$y-1Hc3mPP)-gKfUKo5)vM(pls$Sy%R&(S|chDh^;e3ySmH~XdZD_7#9soezlbm{S8e3tGmYaD3|u z;lGc-|K7acRG+?!j&~@|Pg6TC zD>@u%7cC=-a&B@?tl>H^2fn&qL{i zI6p8y6fxB!d`29430<_gY51iz@cB$D--lEtTt0V_OH?i`lVYZio-!#`xL8e=@d{%y z7^T}?(k!#~HhE^mKBRutA1m9Gh;p;ytpR6q8srQj2nrD@6ib1G++7Har>#>=0m=`e z8rt#yH?uit7X{4tIJa8E&cj#Q`{3=-Nu&`>!Z7AJ!!Io@_Fr1+Bu!72;VmzkKFt>z z`84mlF7{{ew#6fD?qOj-g6qwISN8_gCF7}<5hTN3Iy@ReR9EoLaHMOrPtD@|?;Rr+ z74z4W1kF>U`VLm#Q-|YFj+GM8jh4Tce(d)?%J~&d71_%V;jQ88+;{4qmE_Jm4gVlR z_&AJ#s%JThMtAU3{f2?S`7=HW#DUKN7A_|ymUCh!C_|k9%5;wN`Cb?De2RoB+G)9-BItt zo4FFRP}?TMFOBzPB`E`msXvBhCwTq$au=kU%OR#pOH0L#5V!TW;e|kY)uqXG6MaXA^-du-}3!{+| zJ)@IS_ZOUo6u!DL>&9QNS7TP=gQ=1}P)E*WDJoVJ*AXgM7$fW){8ZmYEl7g2XHjJ{ zjf_emp7cDj6fCnpdA;i1$d<@?!@zUutzF+V!hN{=|NOw>hW2#h6P?1l%D5$WuP_OtM{8y*Ui4`@qP z^QNO*YkOJ*!**ScG)Icp!BEuIUnDmf&Rz+Ync}kiOoHB(Qix{D@t=#ct;!5vo&jD( zVvr5p51^?IflN+OmlY~#@*g^7K~N2W|NFXtdtDSsR*9$9F64e8%W=D!utWUF#hjg*7~-HqZpPyM)x~fls8m`nvT^5}NfQg&3pK z2bA3gG0YDj)&lb32?I?81v;U~P-|^1F24xyehWKc09YEqEIp|bKz#?JV2bv7>Ov4S ztW@g)B+HhC@(CARH}KMsMlkz-y<4LE`v=Q^?LAckRiqgV{EP`Vnw3RWa_1>w4|4P zfQ8*jux#!CbkOj5riSLDB`{l~WnKEyxTNsg67)hGXmA%;-&u-z1ZMPJ8UlxYI41u6 z@F(fFjX*@9<^&#Qs}DN7XeN`Ad$a|xMRD`5PUBmtB~T*0n8AZ)zN$H1b=?n-y#hVJ zH-iws1ggr2JFO;8cZV3@*PZq9H^5?dm&h5+;7HAH8;lhiRVBQrjJx($u5PJ?fTPvVc3+opzE)9=6) z9H$}pCioP}#Og|*aww9e)SM>U{qA;Er#A3DK&|{F)fjnsX1C+4>yP4^Om`68EXzZ6 zI_|V(zDni=A#2Xq|E7nY8h>3tYI&HnK6{+(>Wvlrp=3PNB>;S#N#k7E*f%kSQ z5IGCMj%X0G(!`>FpSa=rjejykpBz9Qi&vR*>3;AdU?m9v%sg1=Dt1kg-^_mCeIDXg zg$=k-JMNhNi<1c0F9Q~bwkc1*`=KK4$Q1KH_kUq(G>_zV-*5khc*5(HP@}eIfhXm; z`+Dz>Eg($srM!-1_c;9N2V9R^#YLSg;(oA|+8}bFmZu1R5EvVTJ^wH2&O4s!|Nr}i zWTp}l8Cf~DY(lAIZ&9*mMn;k{qEPla#<5b?DP&|;M)npmqO6cnX0p4UFMU6s-|u(b zu79pSu0O8Zt=p$hx57E^^BT|bc-)^Lg&N}Nc;wK8XjEbc69Z2efM>GqRj3Url}*|o zX7+N%E<3bkBujFaoFICDRDK2UF$Tedm1FqZI^w*Hp5q#cFq7BEK)s?f^y{)E9%7e& zNO{aIMYJmiI#L-6B|Ud%ePFfRKt~nATXgjvXz-yt;03k(LVOdv9C2$=|FO<}yY+b# z@p?JJJEcOE1Z)jeq9eXqQP{EB$YLvi_WD^y_dcycB{>QpKJg-qNgJhQ*|Kco^7V@I zAanV&u9w)KScM5;z42t4V(18Q=~KtHNl9-p{?b8n7vmj{m_<;YA8{%pMuaFCS{-#s zD`YLfl{}RzdYP4S_j5tJaGUNC$QEtA9BU8JZ&4}u_Vawj2fnh()yFf&^C-cRhl;m2$_rQp~XsY9tQy2t1%$I(Ip~tsGGka-m?ijH{_c=FdNaPN_4$shXyM9nfl=cN4$O z=1AS~=PNYgU2tz?2tGmcq9ZH$;S3mwOtHV@R+`zM(!U$0rX_CYW5mFH&h9+(gN4Ek zDXZY3%k*uNxcU0+9D#5LU7wX2V~jhjoBn$ z;-@~FP8Xk1$ocF(I4Nqby6)hATXwg^b>vC)m7r1IJs#Q4?WyhRnU6TIxylrt37gi% zYj(Vllf&%pU%U%NZH;6inEo8q3_}CVV6)fwGAb7^0c2<)#rFlb$d*8c_8aiF77}bi zjWn1h$Fd7rJgn>DjrQL^m)KLB5egr;PKIM1K}E;{3$WmXOnz^QbX4(^HlCEk#yNC> z(U<|zxCSp7zf^T{&^_bkWe^c~1dL6$ZJ~I+0Wz>UaO&t~D}R4Vx-0Y(>OF-$Nx7;7 z>O}8A8&+-*NZtAe!Q{Gv2#-jx5TBF~Adx8eqb-*>He#MiWKDu`kyRD_qzjP?Rhah{ zN2dBU>ds8qd7|swpMlTe{DG9K-u=bJDk(U~)CR%G{sD@#Ol5wvc0Q|5*upoOTzlR9 zSY!^4Be$UXZ$vn&Ik-)@Gqs7z=i#6-9}F5s3VuZO+PKd>S0ra3KyaTZ(?C2c1&X{M zP@0U=7>Adny*Hu5JYGXcMX?VryCZaa{a|fUrI@JNfdHQs1I`QX>*u#`hl%z-sg2pX z58w!k)d8Zi@_g4X#Pb>z->$3ETRf-;FWLj8l=r>$Ase1Hwu6_$<%XNLS8nmlh+^5M z8)Sx>=5veHWlAkY-QEk(*4r?YUsCwr}0xQd#6Ni>5lwH<|zcpszaBu57et2 zUQWzuH6v_H%+ds%EhrM0t)hkH|GajZ6y+NQtiybSV2?fvx-F=;ghBYyNT# z=F4&#vA?aZdCcrVe@E^YQNf~^53?S@WRm_40`HbCejly&&CTF^GzPXdQn-~Lno0Z6$&$~J9g)KNWI?fE zhDR*hG?&{}awM{%v8~EmmhX@%V6PHl%1O6UKMHP)2EO1O;%fLfk>x5{C|Ox(D>z3z zYe#D0bE!F|z~J-XB`3Hroe?JlS(ZAz^2;ZJPcE2^ z?GibVBxg<<%-s<+`wVf*dE(c|oULzYg)Mi=wHG47oGp&EDheD7e8WeyozvX)!aq&c zQL?Op_Gm2E$u_vFdN@X)K;|Nq&qcJ=eAQAqA>5R(OGPh!_kw4p-NeqDEMb3cZHY(T%$9-~N!3do9c*b%|-6Rs7uvYg_HA zitvJ6)3gkZQA;v|BGZB0IC=zhj;n58snSFq>R`k ziF5yeXq#bMM19~ue|70B(WM{be@9#(QTdx zPS=*ZXCmd@;#ii{O<6|Ud1p+aMQP4)7k3-qi>0n*^B1+`nkr+6J=hr_L+~rs8#A>! z-*UHihku5U{(Y`^tV8?^+13zP)XB0-5JU4hR944jU02d*TT(2DyM++5&s;#5iqoKzfA8`#Q-bu~U6 z&N|>u;Jhh&Yv?tFCsAGV9g8n>{?qlOB+-Yi%?YvQtV5#Mcz{98cDhiYnTg%tX4)9Y z>A6IP+oW79RLDxRt@2>EESJ2wY55_G;`8Gyo8H1^`i+K4K2+&U=VS5<**s&I1_#4~=THFnvvLCqf%LSYLzeT@!}oRWw->KTCja@yZ?=NxY|A1U&)xkAA!+Jc59jq; zZI^0-l`D4SSDp5$U1Ef_$hNzd6B z*i2lma$dNJ*|t}h!q7Yp7;cm=zB6@E^O+!ZAem}uz>ln+WK|LZ<^^%gd(zhEblp)- z!X)Yrjp*GArR0gG_=qN@V^eY_o|L%t%!`S#yYiRCtRB1JPhy@)iubIUj`k#*Vy!wg$+P3=jxUkd-CP5aq58uJ_3~?p4Rsie?rEp2^iVwy8H3yY=8VOk3A6%E&C9SRs0w0}9+fMRh@5VHP@(n2GyBJxqv|Xo za&rEWBWLUPTJ3`;Z&3S>f4a#wbS+@}mFCTUKW}YbTjing1eb;AKqC{$Ad&=qk1t&> z{!I6=dwr1VdCWgwQy7oZ4kawOJ1-_3mAZqAJRPqp=^iiWdT*Xw5F1P;j60L*8cC*w zv1`$0&AGy1YSzz8(`Knb%Rt7{!ey;{WQOMi>Eol#FA}9NUt6MIe2C$+#~*Ow%eln) z@WLU94xQsC?3_dr<6l3_HuAR?UY(@Z4m?3GwYe;kJ#ajd^0JkLVLdd%9T&R7s#?Ei z^QQgKnY$B~$zLnlDlN`e5J7$zca2^1s+JoR|E5?j94GI_gpS`7)ptWn4J&KQub80 zV##sPpy#m+?)ES&^rOJ`vsmHTL4TFkPQe!#%8Yrs+H9TvTCK=aTh3Yce$QjBgLDK~ zBKukU7*3ZPU|HW_S-+{sA?eo=chn*4c%lQ#7KIAoLDTMf3m+Lm??Auyp`Cl-C5Ry*C8}?iZ#P5k#D~voH;Oak?De> zlkKzDm3_=Ne8x^i6G#vlH}hvLN|ru#;4clyE%+?bzh}DJvct*t3Kn{N`%En9&Ys(f!)&|7fvx$Pfm77FxVY)JHqFA-a>3p=LS59tpCn}$6lLR$p@DdBSNV0e zYojd3@aw^ym-9NMthc19O3bz^u0($_eBvz%HiZSl4rRl`P867T{cfrf`fF4zn&I=L z!}VTdZGo_;+3`;MC)l0u8(j`zoj3P>651{#xD35`c_l38R03}Bs8PBc561>TA8(T8%{gM$j!9D&BgrQX#8$J}&qN`_h#|cAtrfaZPN` zG*1_al1OAZ`T%vtyn*w(KuD|Vv|{ABbl1chj$pmeG7*s|#dV&c^JOEhDkZzaqN1%# zyAMD1nVr%;SG;dJU#8$*x)7)3Bh%#XDN0OmB$iLug{=4<34eDi$L{-MOI#$4B5Qte zi@u=@ge1?|;RB>=e=W$O|HLiTlyY~8hWL27ou6x}qGrG|!Wm67d6tMVg+2E;h5q9m zXJ)#R=0qCz4(uxQgu0AxxphWsHEdyn(SFKzFvIfQfh-KzJ9zDqg4y%N+2)DL=W*>|kIOn}H;t90 zebsh~=MeTCk?gEoG^e#)em?8Lpt+-h8QSroibX%0n=PbK>F?zCmq)PufL*msz6-?{ zDhOeoZu{+ti365df|BOT0(ok2^^gf6F$Kwfe5I~(WeLlFq2@41HKGcWAj&lW)&NgFwa63CrJcC)J)$=oLQLMIav1c;11Djgu zPjKiL4(Vrc-K&QEsz)4<(1kMkbHSdw2yN)c*{MiCRKopx@2Z52WQ5@#aPhEpVQZZftPqa96epp^CGNWQ&EXoF@aa=Z*y zGpUK_95E!GzYr)ruRkjLGZ@Q8U}$NS1~pY|noj;h36a+G2 zo38cuo%vonJ-7=d8(&5$gdVb}0xD?ZB$dCv*E)jtEEMJ-bZ&O;q=Vl*}-PIFw1<1E(W{Dbw-A$HyC$GbCx z*PcB((wdbkjWNMfWPOOA(&1JqcAttXHG?8e*t}Xl1x+Xs*FNL_mj;m;ek^+h$4l8C zrrZgVl4{|57a|{#sp766)1Z0QVeEIy0Ff)y!BZD~!`FrzWYdMqGR@Ku(r&1jRGZjx zE9u%7dl7D>fIAlH{>kzL^m-!4t~x(yy@koc=UPk4drAVk-ol!}>K2syA`-8QxGPV2 zYR}!toM3$6pDHhMp&aK=H&QOov4br1NR@Q5Z`>$*C6#Pfrju>!p#{s0r}GE=Sc;yO zheryL`TwzGJDy=Rdi2RKC`KlBRufe|p|w{&eKgs0H1cU<~QVtf!eJiiu{TNuF`-p^5LFHd3&aT+pVX45&O8jYx~zc-MKoF=uc(b zBj!_2yqm))k@Lmq$Z%W70o3N8kX=n!jZhUYlA3=sSu;b?Ax15d#aMWol&Q$1!Y|`w z_~C8buU2L%|HODBS0#$rsR$vzi^kb_lU8Bx7b`<=;PSB1*~t^?jCtH;fIDw}qk=o9 zfDx7p<3y!eO~en2O(4-bB&Qy@>0KZ|B{BAJ1Lb`rnI(R>@Y~$wLXRD}STw2|9ptt{ z9c{ean*{KAp;O09IY~5lj;g90NZGCbRh~a!RCP9f zf;Kf`zFE%wc>Pw(=g>b}gCcH%tewj%8m9rMnKy{+Omd*Qc= zzN-HryRm+g|J_E-;qm8n%q@-mp|S#*(-#G!$;^xDb42p(S+ckzy<4}UI4&JJM^j~) zcl;jfL*0`LEH^^Q>@nX-WvIVr(HrBg%0SBpbM7XGC?$b4(F+pdEbI78S2j&`TAq#= zYRx#blRi=Mk-9H_J>UO6YV3l&bsvq`UGMZ-B|H{&;JhEjgtd%iTu(yXaEW8xsFG5-l7rBiE*AXMPivE={Da-BtIBeg@#?EukE4Ul{ zft+bW;o8Ey3@Y{pO>s{aIS|Wv#KSUYd6M(CId@%*aFOOKdwn`fwdj_iK{;#a*ucf3 zU3W4$H=tHYZH_`+U2|aUTdzkIgU_}L^!!}fi#JrwYOSnAK{>9J(RvT}Ecb{SMbD0< zikNNpv%z{E!`BVnx$Hv)B9A^BU9XcWy+W-*pBnp-S8CTmKZvtSGEk)BbHd*y`~Uno zx13iZL&V6)1qRMN=ofL4-40l)`SjYR>lV1kAks1WKYvY;#mu_d=C2v5FWIxvVRl9) zUQ2HGc3U)xY)U}f4x>E;|2Epu*Y^X_o70_`i|eeY#840YzXL!-v!MZB`u}KH$Srd> zei`ree^tRsA&`gMGCx0)BK80+1@x;YqXF43GlyeSiWT#8e%n<(cK0wi^MLbz{{7Sv zj~Hd|?}b!Q43XqA-EV2kySw|JZmQC)vv4?H$AV5rD%oXp-7I7`j(k->ROS0%h4;F0 zTm4pHs`n8CS);WDC$qSUtWM*o|NL~jo?h$00yCPSN!mQXLoP3(>iQq$7#wifBtn78 z77BElP^R;huK!*39D4E?l074FD6OGolmpp+UTSpTaYTB&1B?64d_UivpCgipxr_9X zN5WcQfWY5(4FCPV7@qQGf9T74`DJ`g4#Iws0khF@0~&7=qs#NBq^HmfjXHD=|KSHm z)sS??Q-&F$y1_z=x&$GM58pq&;5nT7d+rlYQqkH)4%jLSA`TlzS`#!NDwJq&X{APX>j^>*n^n_UHeIf;?^6@~yHs0dLV96I};8FAX zySUM_$#AvH2g|^m+X@60RQrt{_(v+h06$#{_4KA{kQ&;E{g=E{Tcy|BKgLp3UHr=( zfY0kUH}-X)LN-YKjxhl~!XfmZRTiBQmvNbhYt|w<%LtB=2Ecvig065J@!oee#rCmB z#M-Yb=U)Ezufd5taE{)aLkRi7CQC`dH1r5Mul@QBey7J4;gXyqp!OL$`S0h7H^ZHm zkc6`U4cLg@PROP7*64(ekx;SLFLAKUEFpE=F}5p~78##ibmYN@QEc9d3w!z5`IrULjQ?%zq7SM> zq;Ike)KM*jFhFRC%oS|peP%{eBjpL7kQR_?sjn#pbJt2Z7Z6Im*zIXsdrHEG_ zh}6lb>AL*Oa-`g490|3Ngnkg1p%XF)jpz)VHl zuqoTYEB+a%yPtdnf^hZkz1bS~P%ncy1-a3Y$bCWv$-|*R8RFchr5J#GHDhOA7l%)E zI)ADUAUCM2gY)*E#m9H;Wm6jaIWDd%golrW)}o?1e=hV1gs5GhQ$m6=2e4yaPM!u6 zLRhVwzd!P2U#Nl5PR^m^lm7CrZ^)$wwufsJSDX-X;d6|-6!!uI`QymlyL-_bIDiQI zM*=J=53iJ2*rdgvK%}eRlUanKiNqJw=oxTCb_~c`6e#W$g|{cMd;>@s_Uu)?^!8!``0kz-g&&4DH)-1n5Hv zq68#Fbx`0oNF+_vWYJDPYYl6zizxuv%JzGC(}v`Sx1Ou^YIl>J6Uhu5^KXzh8;HLH?Q$xf>w#o^+AQMAIu}v3p;l zJ%Wr-$-ZSyU(DmCVEvyO<-#gdI%{R=I7gE+41FLz`|maE(>FjJq4H}3&rz?$FY#2? zd+RZSQ#tE{enAj)mfTsBOB9Fw)M#zs3w8<2>thby3x!P|U{w?gv7+sW+BrhqXp6BNF{1EHTn4#*<-N@IkvnFS7ZtA*cx(Ri^!wJX z2ERy6O`!g@&R(n)q!B61oS^EiDvs@UiZO#ND2NPqlBs8KTzK!gw9gS8O^Iq!Mm+{mgRCxWCRRDb%>>ja(0RE zM{Scp)_UV=v;r$A2uw1K@~p!i&}(hnHiSJ|mg^@4;h++Y7u#2s~Rg$hHI+Gaw%WTx&^do3=m{5!(2p6ou z)mcI}xRyf>YLIb~JVujbyx_Azvj@iET(s9*GN7z;v0y0>2L!bNZBLC`>t(lz4{`kh zd2D`H`y+(oQXi3@?$!2LHLU&jPTdRsRGl4nL`N=W)>BqcNfnQOlQYKN%#tD3fFw}X z7y1KLd5aE^;-at;LQ1ttd;1Ot1GSge?>h_UnY4aWolgvWlNzewr@H6*akB8A6Y6EP z?x^}Rp+k(Mvd5pWpKTcx5lkKEeM6y^*>H&Kf?N<>)bbC1o`9EX_gEs&F%bN#>WVVGI>|0vP<=SBbTf&It-%j|-AUJ~Xx zmG8T-VRjk`*q0vs>%uk(3_mSxja=AaeqH0B?riewve;9XoQhp`D~EnVIw)$=L0N#p z_95xkphaH0G3i=>nNLox?FLM(T-$$@SgPvZ_%w~`?ag5r?6*-4aXwbT4MaC3$MZNO z68ocmJ-@gHf~zOk^jv0|bjUt8k0$Q`EoQ=I1x61t-99m)NG7M;O7o2OozhdQ74L^u z_y02_GVJwWM=Nq4qgdanyQt7fpFg0ZQW^8=gv@D>pSH(+J5yFeKz=eImK}d+Y&D_F z%0J3WebuvLMl5ZVh=u|4B_sB_`UZr*6R!IVcSMvFa_g=68%l)*jegnLoA!{XZnA-c za$`Grbauyh#^XW79Kl>2WRXS6G|`qut!aVZq=%ql8)(-J+k8-PU(H0tqvgrlaBr$T5vaC;))a=ejJ}F(aBb z?ByfA7T)63&o0h=EFsyw->~@F{@JSS#&fsW6_!1W0n8aeqr^gH31OU*UPPC@Y?+Q5 z|F4c`s(woU{4^_`cZL;`Xy&56QMYYn$Mi6}(ydL~{!C;BTuqubnqx>{&q?%;`TF-g zYq!N!|MLa94yVwQ`!(j4)ODL6l-sQ+|AKOs4HJD{fH^62ek#PNK|-P!lZ;o|lu zuVrS@fDW{T$;)YVGld}5om4eTo^w$pF=nUcZx+nQP(A9{uh(;_7G>(E$<>Y$uY&8y_$5~60>T5ui=s-v({7l z?tMeiYp2RV5L>;qce3U1Ia1Bz-`EHL^G(H~L$8Y6LXR9i20c=dtQq%DMjl4{-y);3 zxC>qlyHeg2*(ZrqxBhejfn#V(Go9ioRq7UN1n5K4DMDtSl{(x**)3LlXiemdZK6K56p-=uXsI zYqQi%|(ULr`q65s6#H@*DA>mknap;k1nyhJ79&RO z%bk7a9~4vT56}&8pkNTnFa7rWqgd^tZP1H>m}jv*HxKSeNo%JtMoHlZ9FLJr5H#-f z)p;#wfC=hH6hON{4#?ic7K|dn11FMF9*{>)P0uS&p zWB4ie6!cW8^sz|;RivY8UBE;ufI$X95G+gmRoupip#l{RPELBQTfw3@@WFOIX&(D# zljcp!Lyacc0L_^Zr1}+uHf{SQx|Mez)LZ@qB_a;UY3PQeInIDIu>gO^)NUtP;t*sJV-peYMyH8?5uN{HEtWI^()?z`iitV7Jls3!n;B zF4Aai1tLj)Qqldj-<}{e)B8y{ec2=pO(?U9xxZG}uz?bd{Se-_nu!9A6D;4416J@a2bIeY%IA; zts!%)DV@>Ee+uOuW`Lv186lo7fuy{VlQ;zXbgsa}Z~!HL;M!ZRXxhLbeY#6p;bPDB zU^e6MMaz>gVQ$xC>P;>Wy$m3S4ZPmRt~ASjlT`5WosN)9>srff^f9HUK(zjn`8!bU zXs}3ZrQUw%9W}bH-Jj=tnvBNDS86(T=EJU0c}ng!%5=I+zA9FXpB%{Q6CR2zs(%3W zhZT%f_MoS3l6IFOUh<(MxYSif%Om@x z4#u>%Uh4gK@-XX$&OJ(80Z3|Zta38`k5A2ZBGqK#?R4`t<$+8Qf&MhdiO+WtPr$A_ zva6-ii)jYCHRR`NR9s%_8m88!I`BK*_&)ygyc2$4{*HshUMyijm1>$C6XWU!pT5mD zn+cIZ-kn%`xe6krZP3hXE^3oyn!-W0Xq6uYjkZsuiHGF(K_Y3 z5kjusBhZdY7u(^pP$x35%fx;_aLb_+$9+B3IXGWa=YBifg1D(B@ggqskXTu9{zACb zo(@uw7-@zmNA+d&m%B`wTMZ!}NszX`mI${B#}JsL=|pG4ywQC~ z(Rp|RH`-QRM+`1p#?YV9y;bN#8bPlZVBl^ztxItll+A?`Q9n#`@?3*zCeQ$Cp2{BC z1H0TG=}gJgr;$H#Igol?@$+xqpjI{9ROT6;_Ys>2%v$(-6Dl=NC*>O#5cp1x4c30V zgTs?vXBl;1JxU!)Y}4aB`^a+c=tH&Pns?uCgiaH;>;AgQ2<)THJ6BMz~nCI}xn#%6_agbeVN%GAr*W_0Qk8VwzOKeqKCu}oC zMj&&!sLe^`fNw~n-9|F0<7v)ZAg~cC(C=k`Gjrw2P{(bw(rng!eZH(nR4r(%i_Zuw zz8G16n?`TlMWL^ZS4*AyPqM{kkwPL^d{4hLqI;<`u&Q-SooKdP^5DqQMa{xK2JEeE zBTnaf8)f%_KiaPye>KPid((FFV$!Y!h-<|X4w(6P6sj2wYYXNWrNy{wecAg0JL{EE zTdRAAx$MG?EDcyp9R0Kd%9Yf`a-`;^HP9FUQGThy70=uPGapf*t zn@C*F>?ZDcs}!D}Psk*hmez$Br!_6b-rJVUno+g;_0ilA*qnL&!R$Z#InPCsogv83 zeeMN2p>V|-ZoddD`^dQ3UFMtui}wcns0MK_{``ef@T$q`6GhXja~$vJ(>_M@)7gdz z#K1T~O0^*uaoLW~>x-juRq??xxVJCpr7@>l{F@K29mmw>eB%(TFLf5buckJtwS3uX z1R+d*a}3w)PkAY!R=|{?5cn?b@bwnA*hW^2gNy=D4XmhkErt`~tkC>t7sgZCOw|2BMVH3HgRf)gdR->UX}_x03rT|rePY={ zGFgX+V~FnEZ(wpf?G?5BvN9DGN`WaEs$Q_EQiybEsFDD`*kpzA6V($K4MXPAr}9Me zO|sKFc>KjTvBFQc;y9eT&EHE@IZ!W}Afk(X`-{?F3f`TH_zGtWjn+`Mw=erRZ>$dZ zbc#FakBxl$TxWA~Kufl*f^&slGpEm4{93zI-v?y1(S5fw(e-YnkO`yk8JEDG;P-&oO* zHjk{}eM9X1_tV=)MjxPq5Y+`;w${8!-jLK&8pLuNTcox>avV=s{gPek2nECb_(@>c zMI_RVQVuF|KkOvz7?#+)rn$hzm5J6!u9mNR!PIL{jQpwg!xd#e3rJX8H%Qg1S=v!D$_0 z!@R_2PBvq%!!cx$N!+WMu6r6c``kasO53ciBsiFfAe87U$-M%He5+^X9D2G%`MN$G zz}G1xxCOQP2yBvwyS|Aoqqd8}q2n}C?Y@94`OlXDAJz?#XgK-*{f5MPD{R%3>Yr-ck#Ju`+sFPZl z4qtP~PkjCGwmS%ZLYiV7g5Pu~?QL{{Q&Nbe#iW2gneAPW>($HiFjS3)hn~*JxfYd$ zHxeAP>?#0kDk>{Lx6VVe#>mi0pw+lq~*Qe7;{dXh6!$7$paAk-7`Y(bp?uQf<&SB%M1r3`8Lgvb1R3mNcXz+G#en`g5E&qvdv0 z@52M^aI#Lg#V(3+3to{IxT$CZ#=wn=*1NPi;az(&MP#HsnTwk3F;>~54PMns^tex( zz@(TQMKc@4ZnqT@j8aPYc`B4F@?Ho2VH4Ds=%oj#7m16FLM)V#6bWPTrPM)gl)$Ngk zBey0{`kT%n8ISjFTw)%TGdwyZA{oIEpiy{Hq)nuI>uBzQfpl}4DAJDiQItvndX+J9 z>BqyCpY_B}zsfl=d8*bGzrgJga0Y9KZ{hP-(aoiOZXS{(n{(nm#ID7KzC5LTpUiHM zj69rjdCzx%(*(giul|gF?wp2GuHLY0|BcX zj;WnwUcJH}oDwRL$BkZW+^GVy-L!k<bH5c;Ovf&zSGXqWWM1R;baqw$J-tOa=DlIH{TAYWHc&VruS3IXBNr49Kh-) zh{+={%G~qRHhn}!FMO>0t(2S*bWWGuJBM(c!y?Q-jcp7!Jv9sCaSSTE-!;t+V~*=+ z<|OB2JTD^C9m&ismiZ~Gap9Hu5MwSKRx0yZ5!WG!@4w?suW>h9KXVm|u!zD$Aj33f z8$^tL7)=$&P*)khZ5qr?PW_#uULj;4?rW}0wI6Vxdd;_;i-Y3b+Y!UW*^ z_zulOpHMmwF3NLaLyddvEb$f!p|%(xWsw!PX6t<#R7*1_|X!1-=$m_{E*0T-qp= z7Nqw#_lfPQ77vMV4ieRA!m$8tPu^eBP+W@6=uaPd6k}PtM3~bj%W1E0=nOsQn&ZcW z=I)86(`wz$@w^?~OBM;zdUoc~obK$RvY2zW${}t-zaG_p*$dcR)zs2B#E2DYAoiEb zBvQy}W{uQxV4@Id(MvGX%x6(?Z*|}0)su`@l+PLTQ6=1tF#U`I^`u0L5$J9*7Z0EO z{uW>5_aZQkbnE2=u4^k(_VVTet9@Km%zSW>p2LkC+gJFN_}~Te`LsY04IFD`OK~4N zEB2nQY4nhCb%0vf>MGP%!(r&f_vvlinX&5$eAkbtdFRKz9I?VzDN8bEPB$(F#@)B<=0Pv)82Y3y0`HcyIJ}wSD*6AptgYp= znS=#bc8jmxlGVN90HO`7nsiiD!|4e;LCn};KVFPqFr^50qHuQb_>sGsN*=?GWi%;= z32SLFhCOQ|KX##H($q8++r{~8Hs74amdH*=E;PU+cYx-?Xl%N{mlfp(FKw%75V9EG zk<0RHCxW|O_$ZXHVZvgT1Ho1*CT>~jug>7-39HIn&uLr0QKdrc z7A+V4$y{7CsQH%})2(?8YPN+GZCnGs}%=TUoo4M0RscK`?*~+Z=`-`{|@C zCBsyr^A(eE%#~~I3OW}M&tPGD5?uM=hWwk$Nc7>*`Q$gpRKnpLikZ$EKL<1Mr?d7; zQC6%R)4z0o%d59X>XHs2MYv^BeUII2p9#V61?q zVN~)`vKzU`gKL9aH;nf``sLHfRmq#7Q>W0Z-?%$`GdQJ!FgNge-u}}R#^;qi^H!2X zA~Pukr|g(^X!hLuqr0Wfrhm*?#b$_SeIj6Rgd3Dp|?b0Ctx4kIlE%pv-g4ls^ zkc5uu<)o+WZdx?|?ti1P;hpI3KDKRLC>yB~b)7~MoZ%J^qmm3Zn6yS0!*g$JF|wK_ z{i&+))Qw-1QQDJO`I2gC=RUV}+6aOf?Rit@BBl)?<+#Hh0*g?9)7x4(dl*Aw_aTz` zF&atx{nM*!?ameOqb(jrwqjAiY@Pcq_!$CWV!;wKmY6c-@ats-7lbOTRoPm}kfZYX zMoTPQF`VEdYZv`QR(pR)fz}qBPS;l`b9!8tS$6_WH5O{#MbpH_n6Wgd zcl_>=tlrAe4X(H0WR0lq6b^f6^#crexNaEL;Mw-&bL{UsG4k%;$)EV_<~)|1%Xwk$ ztAO`97f#0BS#hFfX5@v2T%>zVMV+ToChL52rKXVXlcd8ZO@>7Sg1NwLe1bp*4QiZ{ z1pifjuQ(fxHY#C1BIGyvZNP+mHu4Uk{Oea!r5A>L@(DM8ye6fwLjCJp+vm|wtB&Gh zl?Pa+Yq#7K4t;+RGUY!{L({y#jET4FEE7YLBJ4sC96EiztZCx0ht~aeCsko5ts+CT3Msv4)aN^l#AJ<*Gj1t&fy-g3C6FV zqrr1Gx9{;S%#&xvHEprf$VbwMgft16f5{<{o6U&1<joD}|5*SQW8aJzdmVD{fn!@!pw|oWvVVH?o$#mvTSPoEi6U@gT*R+moc9 z<($ziO&)~APSGzaJhql6?<*GsG7#5#Hf}b|2&J_l(rbJBj5KD3d~`Kw>%km??GeUa zO*`bkps)w4*PC>8mx!o$(5Z?%lF}E72Ln7cdT?=H3>c`|Iy)d5GO1cT-5zAhxT-Xu zMGy&xyYENuf$lCJr)VYdvg5kyY6+_h!K2p~O!7y8mJs5r(hycK!rQv_u-dCpXMO03 z5A(q9w``-wdMLG!rV3%!CfB?oOyAD;ipW587V4#5m;x#;3yRj_s$42@;}l3?mpyM* zKSI6ZTc<%6H*|fOFpPPAM6dnyFmw?vPf@i7J}0e%+1OkTP>U@*9x%q@5g*-hRWM4K zR`?W^^g_XgMHut+jzqitcbP$1jQIDY(Ak94;8Q-4v|kNXGf8_tzB`uVjGU+zEW&9W z7cvieWE3-T+p>K+jO7$LtW?2HQUNct>DhyqOV2}p!whoSEZ3+S7Oax4<`c)2Y8W}rT-AY7EU(R=KJZ5`1y59?_ znsHex(Z8Pg3smoxv|QtLdvth!0+TwJW)x%aCswbiPzC-dh8MJWn-FMkL}oPYl5Ak2 z`BYh_pgoB<#1%`rg?p}@FpJ38<;=~exRx$c!=TVyP0|*rnSr2o8q9c(vp`&}f}6W; zmX1^T*J#p~t>V+~(tGGth5xE)8yh&?$GUFDaO1W;~L;s6A0wzj&!W{Cjh+bIL zB*NXiH{A_Yei@3#)xB}x*$xhN45zdD0U({H+d&LuB$h`v94SPxEpX#zOX-C5``hd1%9n?JT|7>2R7P)0mPs~A4kV_^bEY+U z@vq)YT>M}JB%N5-udxh?c3%0@a^xGKR%34OD!T||dpE*6ZO$!Dx;@(0wm1a>}R9(c!PcHf8BHQr%-J<3Wu zVYija^yj7Q#Ei#pqg!0l30UQB>%NuBdQ{i0YyQW{Gl z1N^;%GxXndnx!$szHcrn@=y+<%`(}5(TBvJ=c!#Jo?Q%)zmwYu2qXO=fvA- zoV|I2(0o@-NrbX=xW`S+(wwt4#<>Dk0V@iI)~9uV-E!|}GuwQ`nB!;l{ztpTu$>wY zaFC1@y&n82B2bF$A}msAHn^Hbo^#tXmprbigq?onHmqnOy_~rkksYZpE+;k3PvbM4e@I z>TBEYA8=9ScBUyRRa8lTTK6z$2u=2i6Bk8^&i7W__^0ksB?c1S?YDeg)=S8Dz9-e}g`pF^KoYvlmWS`o zprARm6Zx%)u|r~o@M%>~&e172d{&#!WE_tp)ACtz$;KR1$JkUzi$pMYiWt^W$rFT< zc5N;jb$UMhkuG@}H!zuR{FBN0Ml*lI#~5A1YfSD0Y~&yJj~Wud;9>3`RXlCCba*2lB{7OD4)j#nSteB@>%c(h#1x zUHjRP&X$*5-k`5Yrovd1wQvPP+ycYaDo>U{0}b~28jsSmV9sQc)ItpsWwFb?#_+v* z>K`5uq<>Dtx!Ga1v@e6i%Lg6d!%wTI}t54?nox-*UD#x!@j%oCWUEAxOY}^ zM+;DcUzetu6-m~Ol6sF6nu>dn#8EH68gYuIpT`_{m1s8`nU{BS4^jzYbZ!3Vy?;2@-oPU<_05HT8TJA%C zI}qVPz~dnDcbLQRtym*~r%zD&D1iXQyo@9}a;c?ZO}hwYMnZ+ob#c*%Mk7WQ~c*(tE2 zmInk8#}ahEgaW0Q(YfZ}@-jRLt4w7=0I<~~nz31Xf>0s;i^zWliFDY5{(Ilfk&22T zrjV-@lKNEnu6m<^-i0(2fpg!gla^8_syWE&FR9&?HHUpB$QkGQ|1a_&7u@(%5Rdf>@|H5&#-q5UNp!<6Ly>5>KLUWIg4 zU>Sk#Fdx`lLp=K*{{F6t1qtF1Ahx{_H2(;as0_jfb;9dW|Ghzd%R>ziGc(0kC%v=(Fotz9BIX!cVE6|J9e^ zSpr))2+n{2a6mcCWv#*$@EDP$(O3q6A`XN4h8`IBbm#D`-vCoijw1G*B&6!AAL~X# z6#kO?uCpnIQy_)81mrkHLR05}djA;EdR#{E#rp)@!T$8jEtz{llM_198@;}jKcE)dW0uIubwc-%bs{% z7j>U2I*xy1Y5NYcB~qAU)77XtV(YX9%&m}GQ&C2%`>;3oTz#V}PzM1)#w{%#$GLWj z_g8Fybf|$r9`!Z=_Q=*{0wR>-e|>U&7|q)IV5fKtf+A7G3owJ-O$DBu7Go?s0A{Y? zzM!3t<_N-X8Tx*l#K`+x@Jath0OE@?+<0$R7Z`wS9{|*V>GLq&LaNY2c{&O)dCdUr zLxB)_jQ85hWwz?r6x^V18qwPhdGoT+s;WVw@7`+K67cy0q1tnv-v)?q6kr5v%{uF7 z*wB56ukAB5?|HTdj6fq&2SNi)?bVXm-A$`S*cyeNBNsDyLmbVA2h~gCe^^VcA5W&+_L+(4$h zHTX64#zD|F;>a!;GO^Y|*c*R6_AJO-U(W2_Hh6390tEi=2!A{MrTQ3hyvNCwPn!oI z$w!`7_Glw!-TUVkeVnRnnn4w)oNgk{Vx{h8tgY`5QpdV|Gt1^a$a^Oj&BQ3*+>Iic z=G95xAD$L+PnRkKX{jUOEF1R6Xoi+iDHiO4-1U99RlJcjVZL0ll!6N-drtG}O zuD(vTzn~nLU_AI5afrRQZ=S~75ktSJUv-ghF2O_JGj&5wwZS+jWPfVbSHb`0tl>o2 z8c?F@`z3j2KTAwghc5rm(r;JsW#ohaM{8tXVTo=2fRjRV@!e&Qo!fiSGtolYzbXdo ziwE{wYzz1|yY_dWv*rVH06XQGX12y?8wp;S$;gW>jN5z)!_`l;TGZ@IXQuoa4tP8$ z$AH4~5)cS~4`M`J@epx!=@^;z8D7f$#pjG~>u19I0&$uj z3i1HcM`?eS#65zkkHp_$vPKy63t>G(Yj@wyI1{}O>)Jhoi;)7L0I~A!xdF@4MI=!I zNlD6=tw5AvUw$YQTmk#MXOl2V=;o!c)tu>A9ZU8Xyn*oK9)Odfpq`1iMKV`YQ1i3ep>>g#;tq^{`MShMLZ2H|ueakKd#&VWRRdbK`!( zQ%EQKfYe~z=3GC4eDGl{Hb=M^FpM;ss4dGc!r;}njZD=jHM3WX z-`YF`t$n?d)lr@+NcUqQrPj1E*M>PF&L+A|M_ca@xGR)l+RpPlIw_mJI4peI;Qp5^ z^ZG*f54Jb_l(v3_RUC=WU)TdZ*)LwEC<&Kvc6tY^qBT)1%GTtkjJR6gUYh8u?Z$-rF=l_RsLGnM11U^U_4wn%^gqD1%x15aQ{TD3zjP@)d@T+> zJXaS$;Y`H8xiH^eC>Iy~|kv)9^9^nerV)QOB!jzcve_SC$tWXPt)`5~* zKk4?1tx+kLX^|IhKTZz|L|i3i&_t3Ujc2a3q(3ml`*&YuIfhY$fpjS{^ev{D7H5S2 zxb9>F98(o$aB&Dd@LXL%d^$vtol-T_-8{M1!dedpsw;J;KQ$sYI**i{%r>Eed_%_t zIL?1c?I=lQ+Ka%!TDcxB$+7<=ioW%(j`9Q0{eD6$&sJ=A+$ayC+_aYtTbQ_3i(0)m z4dP(M(y2#iCZ7<#s$W*-mqJ#eme-k$zRT(eyK*)6os-S-b2R_#=S*XrDtL;`-7YpQSPGcHTsg~Z>79)YPyke%g!&`v_O0(v zMAaSXYb|c51@6c*^cUOxB5EIB=$Yn=$Zgzb4tQ^0D>+K=;ynq4{dNAh zRT61|f$XfmmB-tq@P&dP^xxt5EAdg(=|h<5^`4!Hd`&p0p&uV``?1gYqiu{wy|t76 z2P;R0>$Jt0Ed`%$SG@aG;yQD^Wd+cJ%9d>?zndG5NCw3?4#dK)wmgp@k9^^Mkb1jC z@`dSr(X?x7misuuf;T^-kQgbwv=?=ih$@z`8&UeQoeXyqI^uTX za`1v$Q%OxQ@{vB#dC*q8!md-Ye;$xwzr6VqKM6&`?t^fg>z4&VS}WPSmm{st6)CST zJ!3uc^XSgo$aC3`3J!l7Nkur!r-u9azX$RCaUa<<7MRnYTg?krHwXIlJ#8N8Kxt-X zHX2|b7SFng6qF? zv&f?X+z9=sz}}|ucgwRpNAUPsyB9Mw?rX*_#svuMpC%9F+jI(Yl~>A z5%18-XVdN13&I$NIcn8|%U3ECn$_4c4-5SfA`5bp>(-}m`Vn4c+659#Po-Y_X8%MA zk6cqNA*Kaqt*orNMe5DekE$haH_NL(#d_%f3UX`Om-5Mk{=nYQq<7+~eZJ_OOef=@d2Um~Tx1OTmj z{1rP!Gsb{dQrC5^r6e}h)=}T-?$W0>@HaNL2`kt`aG!4qM-f-%s8z%8=}(cW%H-?G zQ5g>sGv^6+3JcVp@_KfPcVoDoi;QbhJlOx#8wI@7+_PJG=kTxY=Ts?5IV zC6A0yj#kOvmpGTl>)5r!C!ci~!q(ew_CzgRR5A^Zmd>dk13L9PWbL10KQsH=3m`C= zZO*B1gh{y6+r_cvnk!@9-@A~@O>Nas7U@UvDb_N?G<`$by@X zVV>4ZWo9#jrFz2hs%z!1D%$oFa(i2um6mW! zY5pF0F0DOlEzQcg2J|*{p?|iI>I96AnLYPz=CNe_V!6sQ4+LLiYpCa8>HQtVr8geF z{29a#MV0QWi;+f3mEHbBuuIa?!^@FlXkqjbrg}qAZ~{qwizpVQ(qe|HEQL=AKRjp| zSl$p_a5)!rF zYNJYd{j2^7TkV1iK;?Df5^Zg^7VJ+cUo?5%(cz||vc;>G&CF(Hd;08D&~3!1;C1rp zH!Vnobo%pV|1s8GIYh($#HLNgJhpASCO79UERKEP$MVm%=GAV7QVnEb*TE(%*f)o& z;PFqn+rP`88adWW;1yx7MmT3yFt0aeCxi3ugIlnO<$Fcb9&AX@_onn1kUiNU9)3R4 zj)3BbbaFuRHrRuX^!OMk^2$C_y^UW5;??FjPFFRfxg%Y-rt)kC{xIrUgkakL_0oy! zQD0~lGan>p#GLgBwEnsA^BI$aW>dh);UDE`=g>Zqk@6fK5$t&zXPpBEpN6StHs)0S zbk@7hq194N|1^wzP+Omx>uNJ96PX6ipOUAqKvMWhq2Hv}@oqCoP))BgTu;mjeMwq> z#{b@8W7*H@Y1eXCXPfx)ph0cTeG%W))qF*g0QzXlS0Lu9LbYg;OY_M-OrLeJPuqlwTI$3m+;n=Hsf&@wM*PYriKiH>(II!AmmcWX#P| zhS!mfWBY$s_|q`RKLk#vWtg#C{X$QMYq^|K3Xrp2iH?1SQM!;|6vHn=!YV+d*zlC3 zUe>#2wlK~>Bfz(o7CYH|W*02@Z@pD4zD@t*fGAu5`TwJ z=3!<`4Xiy`qbmA$E?eEXnQe8Wz{Hp<(DTZP%7(g1WEVIPuABctaSS>pN{(QyOVCZ8hYvuisIM z{-aCGcQ(`WYtC$euZr@TLX$KB&xspeyh_iYFEPrdHv=lD4}&7qwmu28Y6?ya58pan z`hB}p#DI}3dyDGXJqse|jxEaWJj=6rmwE1zeEg*9Wwq}l1p6_hMfREO7ZigIBbdyM zvJwNb?+5V!aIOIg{liV_+XRR_&Ldt(uD*h&`eD0e5?!RvKgfN`IOA}7ASmA!nkkLA z2DaqmXC;ZbEqCtvnXw;jxP|D6tfjFWWL;_u!`VXfLS;}To1{e@mdHu$)o35#0SUTT z(vt-c+|EUU=$Y1lmg55q+-ylIr|gT19@wt>fH z1pCwLw|Txh=Uc-4FK@;P4+d-rz!0I%$W@=Md7zp*#IH&x;jQawG~>~Kjn*;W1( zeK!(`eQv?p*9~!gEPKUkrc(XoDnI$)?D;Z>1S_57w2dD-f%%%MeN>R>^f$%QK7G8= z4wtjynw6`WW>agQRK9q2y0FJhCEP~&Tw{RgjoPQpR0om!2)4e?3)Y8H-GXUm1s6tC zYY!125#yT!1)*>`SaR+1EBBJg<=W&_{H)IFfH+Vam!GzEqjc;47vixA9#Hi4X}E%WI;{)CX0BBH3>*@X?=MJ8QuvNU$c?ZxC4Z71`jJr63-J$}#;09%RAeDoQdW z)PDx9bf`fCc@oRsie!l}E!J`@$$BAC(z2S4C8_zHPiaK{ng}VE7G5x8J#jnA1J!?B^)Ku_uW{-P)hqE|))zd5KOlw}I)W4R@1~=dLZQT) zy4O!VL(obD7;k=ceemK4={F~dfH(F@hl;f#cwS}$4NBqce$Yj_ZgI-^0tCL5E}!ya zFb&BsvdrS2%_>A>ncpZxZubRFUm2KC|7Oo*3CIQPv+|xis!!W7 z6?3z$I^seMUJp4{q3KkdhCw4NN1^L&mJ7W=IB$)?cZ(t!hNsVw)Q0-1kDc! zTA2NIO^M+U-3Q6|{U_1uLfXxnzE2gB|1_RF*-9cW|D7Vx_&2ZGsrx5{>Wt80h)Vd> z)>+!iG`Ev|%+51DR3va^+h3(sO6t0GPmSOGVnB~VKxi*SLq#}=K9EED$f%w(R!=k( zAKD^aWs_$d{td!D7h1o?BK*>mpKA0!vk6Mym0+Z3HSLljlg1$}XcOLl+S{#Pi0qIIrf=d0bHxT5V#Y*3Y#(w5KP-w&7oXPMu zmYv&LFwa4KSzs8HlA@R{^AdPW#9+kpL0WeeK9`M0LU;o@#1~5sB;Se{>@NkA-ZFo*Y;zh$8XWaFyj-3gbAp zpOBrSMEcpT+n;nVa~+x2pC;qKB%fdZ?U@;l;oj*FB8**086WH%9lv+2&${y(3h@70 zX{%c?a}(;f&yD4^otgTz^sB6WvwAE955BsH>LlPVYBKZj>d}hOJkb6-eMMe?mstOO z3Ap|p@X{VO<<#F7#AVOYo%s7N2!b`gITuSQK z%T+EE_TX2F3muUfXO4mLIDMDR##>59jN>2cc`r z@=Z9N0%o-W)v-#a9N{TXI`S*8v{(5J11zthhd~ct6i>9ZUV6eh53$ z92M%%f+vhkKQ`RrCH(ti>^IxiPX6-&@aKnrZur07%Zu>*^CskbYR3PY``QlK4CY-a z5`7pQp~bPP3IK0hb^ufu0_mX{_$7=f{rjuYkZpGQ~5C9ko<^ zgVB@XNB|BVXzUgyhe-v?*~!8y&ZEZz_>Mvvjwe!vAFj?^M_c;3rtTb=Y}cU}eg&`;Tlh8^j_Ok0%$yQ#;-TDIFS_l^78`kEGN6uRBm ztP6KDEDPM6r}9~zC=bqj)KOL8ZfD`5DT!{um00}g-+2{Yx;g()uVS}UwwuDqeOAUI z>Ow5!ruf{dkooUeP9e`)QF91`UQ5{h%@xsSiBrv?OgXRD|BOXU%FVM^Bt5ejW=pKF zKe9`?f4&vxoSLvfIUYF%)4>Maz z4?(do6}k#@9dbv?EO+OYF>L)(5fjF~1s!Yn{{D^aM7Q-b>;KJ})b22!u;)Nd&@cql znuC+USi}z;R6eIUFj%}{4mEyhW;^%KX#<9>rU#%D}FQ4-psaNwo5L4#4a67dw9uFK0OvciGd&`pTu`s~X8)Gjm~ZUTo3L8<2VVz9TJ4tt zXIDNHW~0R@)i_=z-3uxH@7ZDJMxKPQx+aBG$w6eFE&njbq^%eR6`TR+^v4D!Q5_2- zdofk}x-Jz(&rS?Kvh}q0s4jHFiX~j{8x1zE8#$?*(B$1mlVaOkAibb^S;O3x-1)9# ztZ9E7s;6SINwF0ToMy*S=g+`?RLSw_-Ljx8ZlnF8VXi!*P;pRDFjl(PYh)c+AIT{D z#5BRqX7@sr!+#UPkI%?_5PI+V)e10-GK1bTGJUCBzE0&GUgf-PfWa9R#FwKw&B@Iu@+Rt+eS?P)sk&gVH1<9)A)O>&$49tr{1FSF**Orcx4Ce zh5e!Gy)Eg*jS<_vvTjo@NfK}Q6n!JSvSww9$P(dHldD&(edK@mIh9Z6KSI}y*ysz2 ziT(HJTAf2KUKE-RsWu>9F{KI`+qsebayPlm@>sOW2Y!4c8O5dSC|>_~OVo6zIF>5k z_ESU-CHoKjDhc(bZoeJeHH*>$5fScI^lh!>%y7Y?)g#qc6@}!*QL~z_RJ2{ZdzGj4 zd3Xz4xc@ZA33RlX;{S1ib?2Wi!aFdJ%xeKI)R(U(He710XJ(L8_Y-uzW0U~gxPW() zW^gV9!4yD?quqIT#T;hs^|;uWX7#sG1ivmU2@Y|X#Nns)X*$l*&tu)sarZD}G0+YN z$S<~<6y>vM@eiML9C_Jae#CG$(`ySZz+h_$v!-}_;J*jpN%{m9Ah8}ass)+aD_}v% z0awH@CKZ;JXl_g_s8m^EmWGP6db8EK!9!D-AG#*X;3oIz$kV35zt3>v)$r;luAMQO z-SEBIn`E`i%SUo{sjr>)EI$v$tkM8Wne3KzwX`+an zqx$MdDa`*4B_wbeh#u~>73ZlbU$)vq?ifI;lq+9b??ymqjB|-W%hj8YUgwdqXbv!<&{G0e5>Yj37*>xw zw#l@CLjzOugEu)`E+g$+Yl|XWwuTm2);O)cf}$vuRy`CWMIJ-Vv7U#2v{B2B!Ph4m z{X=NfbMxj>ksTcCVh&cV_rAwbOo>C?c*%>}a~clR>Cvy|->oi9-j2?(dP7n29j#hu z>n}BXwYuSmLU2?U%~5EZMMW{mq?uJt5wQ`C+nnWzE;Wlc5Gv~JGf}JAD%9atDWpaD zN!85g+!PdOKy&c-KaO*sN}S+w)3eTUgkb4q-;;PWP->*f#4e0JAAya<)TpGkx<685 zwZ-t>ciCCWwKTx35+5CZ_OFh>hr~?c-NaO& zx7zl@8>*c-#O4!+gIrDvcG0}HM}dYRC53I~x}ij~P!)UXKjR^M_tkaZ#u49nW2$MT z7?t-zq$TifL3REc63&-Rt`&R1{pPb{RmzFtY!xZWZZ1g%rlu~~GUZ$=w&4P%2JaBr zi}RMgj7oy+EE{d4c(>x6HfII_)mx}Gox}g*bN=QK(7`9vxfs=pGKgu(z?rU^b-Eo-&5R> zQa~E(p)mix9k9qH5Ly>py|4aS?*!h5FGrZ|rNQos@KSiI)7PNzz9%^+=DcothYS`N zJm-ix=g!^vu?`#}hX7#i?m0G2VI`u03|YNh=N{9Alwg?xD3u4n;R~s)bG<*qfF8+( z8F2Nw@P>=c+E*^UZK8vXFqa&ov5wFCe}?jG-;WOM-ZhoW4XSb;+#XZKYg&f$E+Au4 z9)L~%@9HcXec*`ffSqEgEe)`0)*Ik__dpU^{_ryw7A`(X0u_I_mO~`J@o79f&&lp& zv5Tg|B{^Akz#FLWy}{WW`{f7-tzeh*GIzcj@R@GNWYaJmudZs17aDh=4RBq-<-QNS zuld7gY?Pt%g@WW1>kFar%^!g^-b=MqShy@S=}>cy;4EJQiIU_zt!U^DFdae;qC<$k z;o%9}L6P!}5S)0jmcVFsZ3U`bY6X)5RN^EwW-K8+qX1fVh^lUTHX zO9?j@u1k~=He&p_ua=PxVr`S^+E*p+${NV%d<-@9`3tof;Z%3)T;-Mv`c>841Uz(KL#F8x^(fb zHUqaAY7jNRPHn9CXd5}eb{cW~xR37SPl@}GRzovF@IJ{mwd zEF?`siC#7V-AISTO94?ZtA}LAAK(SV%-LQMr}M(`b(h$XcT@TV{+b=iGly1CFh(Ts`2n}O#B7RC=(P~X`K?rcOX<(Fibr4OPse&;D*mG zCBCO@mV0Boqg&5xTJ0KE{Ou#EFyn@TbRmrU-kY|}+f12)6<5$PotuPo)^}cIYg^bi zhwQFIZbu&)24%^Vtc)25wMWia^xx02V&8upAZ`W(LiMi}=J2@Wm`Zk~w^MGrr8jc; zMoCz7CV6M|>|{m zkp@m{!CHE@yONVt8Y5_cB>L>eAcY?%_qB4%UYgRGRoQ-+DpXLQb9gdKLB+``Xg2WR zYplA5hZ9&$uBGt|No~Py{CY*~4LgnDT({qwtX`d5xoU+Ckd}HmORJ(JdKG-K7IvP? zDSTBSGe;M6*OMLDB`#7Enk(uy*6XBq2s)vRGbIH*2C-QO=<0Js)iPVRswj&t3|$0c zsR+|LfmGv)I?j2w${_xj7*11VGmnTsCDuh;`lU^vh!sLfRyOks++($)g*>WVG%>+I zGaBWyUzoz?C`}u{2p(nk+QKf4R(w6MNZc(+bAb-4+2%~^inRwXl5lB;tVm5d(&;nS zI6>XJTFN}o(zDv^cZ>l}%-9O>Vz@o3WP4JK<`%VDda&5;dCbbeVv z698>4@BdI^hU>+3^m`qbce!rG06Ny0^L7U@;@2u{z_WVvPg^I2pKm>B=F!`?GLL3k z!rPZIOd{V#ZG26gq~h; zC?aK2{uP_j_wfLD%Y!#fxooDy`yb7K=h#FVVQTOcFk5^UzixxLD<4RA{a{4G;Mk>2 zSK8}11{0wLVyixjWmPN;HEGxY-|4NHOL1|S;2r3oVk*R+;BW@5QN7!@uesK&4CH^O zeEs{x-<}W{8rW`H!17I8@4US*Egky6+ZmSUO8dEvTFDUli9VIh&ieE2JhQB`K=aLq z+Ns=1WH{%WCF~mskTILo zn7AEw+{riRi<<<&u@#~@8abBq7$myd!%>307sIt|R7#n$-0Q9=mnn#W`IV!y#OE|! z)BT+H!B{E`x+!I+J@weFJmJ}i4w!Y#fH&jVhy&4sm0LhKbQ-IkfpH%r`Pq5<#Qr1< z$Q-z=|2*Xfgiot*7U)#h)_5?$jI!l6h8sUx%f%ng^Y#%M~6<1 ze~IEIDlg-b4Ok+v1O)ylVaRM0#SnOZcGetTVAYt&@?s=lS9f%qIn7Yo<3L~3u|;$b z#gO54UE)J%Aj2g_xdhLfL648SN$;G29P1a^#Dqnb_JMC6vo2dwco10E61~t0NM6&x zun`1f&&jQ&f6^u>kE(|CdZjqR zh^7$!r)hVZ^b*$OfQ%iDRa&+6?jZV6V$SdUrV&;q%?u3j$)fmeESa~Cv)`EM!dq@Z zC{(g48auNNz~&^<>9W zc4K{#gRS{MOK8&JVCr%u=$;A-6Ye)o+4iR}|9sqz*fah7nCTX^?dqzWA@X>&Tt^`Q$b5ko!wwobHsmt9pflC-!g?PYq7w#9ZctxkP72HM5Bb@I1^gfh_5 zbV>Kb{BEt-ip6VyKB1Vn_|O_XKq%IZ;z=MmI+C!GuMhQ^O#SvOlwZACR{Fu>k23tT zv0wTP`}fu-wH{_*f1U5L<5P>f*81f3Tbbs?%?Be6CQf|$R2IBZ+P$9W-$wuvROX8@ z{F0xW>@Fg5dn(-tH>=9zkNj{}$L+ny)O{}Vp&qxZXi4TEb4f<-f%-#8qRc? zgnVEhs%0OqZK;07t-tf&hoz+5WP|TY9ijJ%dKlGE);*#se~zk#_sRDCjzafU4j4xc z8g;k{s)*LTII8NNR>>A&yzG{goR+(bhOQF22|X?Fx08PxrPpgHooD=_Rb`bQrDNi9 zcQ7rbOY|y{`?eG5(4P-|qVeI_v3V+zcx_Ych2`#@OlQ?a=cMsjJbfAH40nY>3Eaq4 ze*#a~IgNx3TjMj8Ngr8-u=nJ7MPk?pC}N@V3aw=Y?mGnDNW~$B`wMNGN@81PmWhuLFbuMRu?0i*)3e78DwPXJ> zd@LHflGaXBMaeP#g6FDaOApr^fB4LGzZ#2m>Ez{(T~;@XQzyBr-alq#>@j@z*yR|X zQ-|h297B=Qf`r#BQJqJt_UWM?`RYdpNn*5eKJQraU=OHTijC+vW*4G<+?8ou-9b``zS`4tHCCUTz|uV-JwO(>2oB^w zV>|jKXbCh-+9c^*?2;_Md7j7>ibu8*Br<#x>Be4mK`OmI=nqO{Ul=3pbR{R!u$Q}B zdp)ACTqG!Kw509UT<1Dh&b5?a%Y|bJH+JJAOf?qGPlyh-Pi*zM7n&QQV(;Il!|*X~ zXAf^5(}@g8@pxGxrmZ-ILU$zQZ^_V5^10vDQ(cNorvUr*Rm9!6)uWWmDqyZCDZXN* zKtB6}yp8fA>X=DW(!}1-^|)K<{QU0SYkYG8nY#t}52|FztQJci8@TC+XXw;g-BDAv z>8#hC2urTjvGjgTw7c#0{7nSDw40dRTq^AovOXsIo_eVp>7LwdO=N#W-;Prmmflt! zjEpNG#JeNPLrAS9zj@8X=4me>U*xoo`574X3C9`>lcIFtb~g8_Uu9b9Dv_xrJtb7} z{u9sBQ!h=#WZxy-O0dvusg;vUt7PxRJm4B%$AZeCFH-z{O(|W5!f`_eB@p#KYO*_Y z3f-eL=bB_!Adh2XQ0+J*Gg@fgnTn|CL!pw~MT2CH_FLPJfM~xmrQ>Q7!u+yV@L-_1 zW-Z%*Nps*+Np+9RQ9(GFiF-A-XjdkK2tmp^%6#EzRaB<0Kh|H7EEwJ7IcYB%+rVW# ze`h#v)99KCho!sAW$`JV4R`GCp)(s}!qeV;u{vmQ?!ATkfVeH6IP-79sVsZ zYDgK3q4>-FcySvQpsCXZtO5qU>q$(@+a3yTm3t7V^m|lN6T){YHJVJp*nP#sF4m~~ z<29kz#OCD;^n0T}EaN2UY!xaMw>-mbnC=pbR){z~Ww8z%I z?m6lV-*wFIMcA-x#gWAwyP^!x>Wa1L$F79A!3|mdx8)TvH>mjBT!Yw;-_0yrDq0=y zO_H9jUT?T*5hL5EO~+%uq5bk{QI=D0dX%;;T2q>c0J^`21p>g;l*qkt;xVq+EU{{D zb9ZM`K=!rXFN=lEMBF38C`VTJcCFW`0ybmyD-K!y*8^j*ph{ap}f()}Hv6I%k6! zn;;Q&x(+{H@blJw(kEM#_{X&6e#|&qJYC{&BFUz6Zq&H)!y+O&S3W`v`nCWa&#D}j zD&;fjmMcMi?QxC>TC&I4TPAtdv;v4bZU@jq9uZ|ca$dks>S%wCiXV3vHqR~SId=86 zbJ_MlNzb8gvO0-iM#)c25k3vfF0c=@yocaO3!R z@7P});YF@(b&wSDgS)v34_Mo8g<=&w$ zu1vsXDpPH#x{gEYxAK8n@^YDSRR!rrvjo4olFsgnw3*^nCx5?zaV>l-tZnVX@OW9j`iG)suv{!8&9Y- z%C-lpix$FjjE*ZNWU|x`jSQMJlHU*R2vlUZ+_RP)iK9P$DC{<|U};oe^_YXerQAx9 zF3ui*AG)~q@$Gzrn05i7L*nzXb~h~s~yCSntm22|MI{+(?^_j+wU90xT@7lLoBr)hY8TuGflpy1S4nut)L@k4w&vvr- zJi0)Ep3LILeOpA)?}lYe=sterArQUJd|}g z!HkEbo*7pphZC%xACv>Ph2@k&z_f}?TBwym(Rm`=R+J#6^Zm?rLG$M}-KOG+2tuUU zk|S z;I!A?uZLw;2w3$v)611*qJ%lQt#W-RT#vqLw`ln}pncHwDHE~FmBeu^6q8!qaEtFP zF&+Wy{6A5@dihe6crx8mXb-k2P)ZD$y9t6Mhv=8fccsajxIR)zE*=C5*4S(Is*9J} zcM0~+X2I|@{8A!I&XfTWMn2mVLl>n8>E3){Ev}P@vPXCZ0TXjiBk;LnOFIb-VyF7t z2z&*P|FEFGAf~vvS6J=N%Eb3&@Uq0_Z7@*xeN5e>f7&O}K@BZ~j}Kx;B-`B6?xd2G zq1}6$9>hNAZz|ZEqluRBvtJn*IVtdspE7+SRv>t^U zoDe-2KkqpBnOsM2d}PP-CO7s?`Y|zWX z_EZKrIf9TQ#Q(s;jr8i=afsKY8nr?35{V!iO;SFFxy>gk_cdy#5Y)1d;Xdd5jgHc$P<>?bMn?hI22;U>s3q zXkFFCq|ZU5x&ZI|jPBCJOJCJ@rdrsf-gECU)visf&La3;y*Fno9e>Z+V@@Es{h@g} znxNOUP{?=eA+~ZWz4Ji$z72!a&fBJtv~S7>;s@HbH9LWV-72}7^L3J159nby&Dm-k zpXm`R+bOQ*t{215;bc3lJ6uFt`W)GoJ=|DCH--p2Nkpe<0%YWXuP5B_bXtGP?v5Ir zuU!|b>h)`WeK`Q_tW5bb$|`Xt1sC!$WChzMnS>&k)~X^pqo;}9ykhR1ETq4UN|?ry zDx`{}g!=wb37>nKmy7L}D1Jv{aOA%2w^PP=rg$ugX|kANDDL;sIul(lM>zgD)Ty}v zwB%!z>BUnfc}X0cbEnXK(l0a7ckI{|dKJ*vj*n92h3M=pY!BaJ3RA$9xa-(hX@KUi zBQ}`OUsN6seUk)fEte1SIdkl6KAjGZ46NgiWxi-$KpGkR*bH@7aP8Yk>&H1(J&h@K zS_I|{WK#He0fESw!q;Vmfb?e1-w9b&WV#>gxH-wtGtGAQN;4k+xJWD7dJD}U;_bB1 zEm@loCDh$JW%5T-1xv+>V#*|B_l`l!b@Z;71l{M&nCH==z{y!3d8*L zb4)QgYgvQ3`xcs*a{Pusk9#cl_rB$UnbV_vr5b*Z9BRcdWrDPXw87yluRCWkEHVks zXOf6S34GCL)LMolYpgiRAOhaZ!x@-KgROvf@>D0ODmxKjxT z5=5Zu4L5Y|}^PAR~{86av%Q4r5?|J4&7j;2CQzpmUQN?oW$7>wI& zDQouN43f*PIHCVI$C&;#s@n(6C!d-WC9lYnMN(z*?7@Ax?pF)^(yck$bDiI}3Db}6 zp?WhPsGVR6=#s&x_NLh{nDqAvjqU&xt8>WP(B`&!k9)49L2LZ?x#;yN)4o#IA){K_ zyPe**7Ifsv6*8zeK#Sw2F4VF3n4B!r8y|%;?J)Q4uIDmoP{la`#$M$6O6!fC*DI|P zct0bI`pEDCu4keV$-86dNcjU1Tor>p7R0YPKm=RSB|^ypYm9ojBby1i|9E)p1lvtn zX(gy_M6X_UWZm1C&6wUhPE!jjxo`vQhyK3HGehBFELRX}>}7T3zgO^tm4F@jzwiFv5NQAVkpB}g`v3oB z|DWBnq!)mC{RQ#IYihPvMu*P>izOd|kARrcQknVR4fr_#&0K1N9B9;oB%8AW(v7pB zv;RLbGZ2xu?B?WLz;6TbKXL#f%`iaoRfhkOlmpm+&ml|{Dd<*SY(CtVCKag*AVtFV zVt+d*=*$G1xALGLIX`7VxJmcXSj~WU=*MXbCd1iwJWi`O3a`3oZCg8I3`d_9$ z9-i@aD4tW0!yg7`g_S5@!=|rYjF`?o2fi-n(YAHn!o`FsB7HT%LZNBy2RZPIcuj^S>7WkDV5N_<9!*kd_hap05n3ad-r>Ve>UsHHFYYx%Uw2 zJ#c>tU?OQl$b~ALYWcdNtDVW+XO3y#!+jq_$my8MjZaxuT|ld`ob;Kc004nO&}rzJ z_GPc99m+~ceF6EFm;+>xl-l~qvCf?gsZQZ&NXuoqbZ@_ZG8-zU5B zyZKg?uV~;OVfxq!n3B05dzI1tyIJ%%jszdeP04x*l{>p~ph0(Ewzp)Vn?oGs z3D1*Ftt0RiM(v2ce>ESTkq+cII<#9V*33!YIRN7R$m9`QXZ6KY`@ZsnRUr?JYA_K& zn5e^!N9&SvZ0ozb0Fci2iFnu_zupNI8ihOYTYHwTIx2nat}`aXe*i2SN{x#ya$am@ z8aY4+5AgMEy=e!Q*P7p>rvom~E6E#O;v;2H_yL&n{FFzgLTaT;<}B=6c3_WFCP;LX z+rrFgV``mpza2;wy3q;(VEZ&OKE(m-0w$%50ED417V(aOc^@u^7QI4=nVRL&NBMyy zPl=Z~Uh&{uj<+*| zt%Y$*IICk~a$U-w`p*^fMfU;LFGWyO1g$k4EiWd!uigV)mdUjKM~E3P!eforp2+Ik z1m2s?#5%N+jR9(Pc!>hwbChkc!Vwca1Ka|KgJUQ6qm(HWG73A-$aI^&ZLeMBEavgy2td^@;rpajq8iG+5tyZ$dZHjY)qAk6q4dXRO zB^j6wAn%p$#y(b}$a+WFjWdjMYM_;gG5U+fYgh333{lz6{IYiYV&d_%98| zbX*)ydJeqG=9SZ=u9G(}3S^kfGUb-mnWy`i!!_5{Q4yAewDwX*CTnN&^ix_Kf&7jZ zyMr0Keu5g0Sqnb;3%H1Jv?4*5iE#J#nP`YgbTnEjLY+`fF30nTQrJgb6=?4;L}-<9~G8$3e=PYG3 zGFFj79`59t48N2+G7p9>NK=_9quM31vEAW4xI}c-Z!RNsR3W;&({e~DGzMMWl#J7(Y8?ORuB;hCO{AjM9Dz~ks=p4DUynua}Y#DB#EG8$yAXfLy^RUfJn|sL}C#n z6rrHtTZazs^Njm`_x+wb?zm&z^TW}jsXBGeKKtyw)?9PW^)@I{I&v;&gR?^8xBR!h zu(^zAJ8fb9l0W(X0J#&Jth)L$6leFBg#8LZjQC6HS8%8tdwPAw$T+Se!TS~ftw-*3i1jSnF`gQk9-Sw;f%?FpqSYxmHL z`)`t3aO_g0Hu$e0Hx%Y+F^AaAgOUS?KVsU*AJ<>S{XF8P$e(TW`A0gtQQhVwQ?GL_ zS8lg=Zro!{;Uj-u6`Kd5F``q5xirIdq5B1n>mvP)GraT1gFIjEO0P)t|Xf`$4VTM$*F7Uj8feJ5LL7MeL(E zK_6&G`WyRrihV95?@?&iI5E^mPw{`oOyTMzgEX<4#qyD79b`mFM8?B2XA^lZ z-n)12*nF1SpjxfBM>!APpGM6u67PN(ubve~^A31OF~-#C2e?@DTQQF#4aEIq~ zg@yRLpf4N>=$ZrJu`+GnT(ht1W7P1hiqtEAO_b+yF|S^|N_Tld&4%H$Z+mTg1EV4m zyg*ARcv?^*B^~sR`xRo6!u!?(OmnKQ9@2Yb{9qV1*fnt4(Saqsx{%}6zGqxFG1u{C zR{|%$CKBVyF{8m)GYz^QIL14q)?Pe@+wBtl0j^ijJuS#<4lr1^PWQga^5%TMg_g@W~0Y}l>b4yE>USR)2Eo31f@)g>?<>oA}OyxXntPea` zCBb0+HDRVl(ph3jH7Iv7Ysyj*+30MmWg769oB`;hF(Kgw?OYAC1U$jRsZ!w?oszjynxkYX8SegYLZTl zuXHKxDvM^fK!jS?L;G~Fbe#mT1=+jn=05y+t>UkELrwLbCDL*3`bBo~mv-~V5_+2~ zRBY$8>wIg7Q3j*Mt2zha>D~zReM}Tf`D!_vV5`u%=@0T$&-K*D2vi=xL3N0u^D#(b zbwPJ*;1@8Pb>$4|E*;@w!fbDWQ4#5JY?r+n-4)AWKxv5qe091-u;V%GsNyWUz~9JE z5Xf$BY6Rz*4qH729^Lzhk*4+M6En_{ZA1#RzOrwzo~?O3Dby`#Tmk3lfi%IK_j5?62Z|2FK zuTQ^0kbHis!m<{n1!;%YV69KpAa76+LTD9TOKG@%Rb&m|6W4u-hQ~dbHF7jt77&1V zQbV@<=GHf8X6qVVj+YT{hbwW!R?!JsG3wHic5yaV{Y4p7$z47fCOIlP1x_}BpP=In zWNnCdaqR-+NDE~`0=2KtI3amdiEOetHr23YgXpBna}#-a+S4`LR=0HX@@9taDwO>y z5BrLA{c-UUxj@&x=C)rxIS9@wg;m=Z@bo|z`6Yo(;Sen1$8HG6`r=T^Xag>P4VMI^Z)E2o ze%RcKU&ThpeNo6Zx?xb5^jzz=3kMUwblmo!goc-$5h$otrX~J%{}z&l3FaD9^-wTI zB;@S65gntdhdB0~e`0@(u^-$gzsJ#rh6fC`nOSz8swtKCeRiTw7o> z{#>{)3~8$kG!$Q6ID>41e;=P$L2P>uD5#Y_z~vix^_c>Z^BM@g20&q4bM*-=Qa$?X zxCXkw*?vTH0LXF)Bn2Hz@f8S$090NpP&X7o+A_=(vhlC5kX!<6(Y&uA`%}EJFC(B4 z=nhTPQF~I9vuFP0I{Z00{5xpb1;p#`|M-i)i2SNQ6?K@TZp>Nf}QkFD@`{P5%thy4lxjmHt`+~3E;KTfF}Q%n*@9?4$^8w-jPt^&&d;iz>_ zE@SUz3K{=bIr#bSNV*GI>`2l5#_yr^OaJ=qe;a

jfUH&R{ZwrIG>0@oBlhJA9PHp`6vui;?pY)%v{w;3jMS0PJQdMzw7m5VsW zBY!=L&#MqDSi++$;?XN}H-V4%ccm?665N$W)%i~Sb*B+C6QH0_h~`50>Lp+d_XQHS zadBj_-3YIJyaQS2+B=%d+A|#)!|Pqo*#8p`0?0rjUV&i5z5G~jo}SR6=5idQSBS1} zd8&0WE~GJrC*HL2`NtzmhkS+li_OF5hblV_+8fuQ4p|RwqBd|TW$sJ&AZAY%IssQC zuY)=ZN!WK^J*1u1NZ*UJm3;zMJ*x{hVfsZV{jT)=#tf+#f)%&YBUEhje-AkB%%7De zf5q=0X)gltN%z{qFfsIRFp7)%Ta|pK`+~o8?;4m!c^RxaS@6Tum1qKiR3uGz|>lcJ6 zu$aw~JK*b>_|sS=By2||j_ zmdFjXgd?E70!B~tw{HiH@WzMN-R*@VjjwfqH@6w+6AEeix~i@2otcG;(T@-Ys1<>2>-#iGO7tU`$j8$zOhbZv`SaYH#@V}ETmS|AvKm-jt>Ci6Ii- z0lBy}FXs!mCX)s4Fj)p${Z|h_bFTJ zZkPxVP`O}UqL@o-$8He*_NZVJN0dhC!Wgy@==dEY?&ZpK#n?Yb_^=#(7y>norNsqe zsME4zr6td=#>?9bRTOUJyit0Pgy-xoH-+(@g9i4c(cD@CkWc6rH=wvM`(`9LaC8>< z;2z^{(-fJYp`sg@*p#l^F(lN*U%NS$8#hXial!h$4|Zm?sQUYLtAS{V>c&kVd>hm~ zMNJ^m3-X;K8MS9H!P&K}b`@g>tY8G@UN_11BhD^^<*m?7Z;WiH@f!|%gLDWth4Ygy zjmno`5>WD^f5bJHqg|L9->`(NY(yqC^ay@bj`}hF$+Pe{M-1DkbTdF>K_kEZ1Ymz8Vo8;Mv2%m+h(2QieaK8i+rE zvB{n^=uWo+JkH=|8rKO-O7^5G{S*A59taJ*?#Q1KXdlQo5cPuQ;s_A#Mv>&Q#*Dta zokCLi%ozMH(?$rHHrc9IJisTm>f2AyBRSEBOMiSy?-U(`-NAHsk8{gY%Xo@-%W!GsTYn5;aBHbVSa|tOZ*+>y@^_oZ5iCd#;`o|u+We8Fvu1D5jsc9X=P!vGBRN3azCjsdVZAF(^h-|U!Z ze(7Zrj#o(uup&FdlCXv-DJIcASQH78u2Qi6@G|*=k;e!8gsJF=E(fE8(I8i>8b*2o za9Qi`AA%Qr)$pf512*1MKUMIU>oWbRr<3B4`nriGfFhv3uh7KcGbRvbZ>vaNOlah`IZrJ;yxRpzEg}K#XfpF&s>heO!&> zDU(sF{{a*nB*(U`-v8lKC{x3l(2VlSSH~_WRG8X<{%xUl%N7KI#5n+BpUmehgM#J_ zv?J`vYemF($O|+6UbV9T!REl=7_*1e&tNWsY|fwxyt1lsVW717YtX1>z+#7rZMIA6 zKD_(y1dH*r4Tvf!CW$lUbiaJ@UsrM)$<5Q|TlUF!cJZelAQfc!&i(0?RLk|gBLK{2Dw?jOi_b3pgt04y z+4NBmjiQqGfe_%Q?S*{3a@&!-9~qfh-Oi=FNh-yigex)(5$C(K?0!}S^G^3wI%QQw z1b{#vInrrGSXGM6(2Itv@b=973WGp}xYbali<8CFxlh4FbV+uA4@&W8lLRO|nj!W< zDEj43nWtfIMqDJQ*i4XuR*5Mr+WE15q%-+vQd(u;3vAbC+}40MjOgkX++4vnp;}Ju z7B(pAZ+jy9hXIXeZ$8z2u%CJeL;Mwq*q^Zb>~^iI7+lHK(3kuBgiMNlp2>%ytq zfD&=!9P*7l@14E>K+(y&0_TSpgx82R9Vy{M`wklf#4EKO9Dfz`GgdBt0ioA+Pk`A;I@ znim2-gQxUL&8uwsm`o1RvMz(bK0?s6`FXd(k0x_dCx#M2kb;*<%l|flnE0AF2=zBJ zouc~=vfcrsXc%M@QMZK>2xxB2dr?IgBD(?Ho&=OOLS5$i+T(=m7Q~N@#PI0NArl-S zc0O%F901U;2>k;IEa9tsITV0t5NeYk z0S3%y=;mYjlVe~OW=dL^AK`&9l7zFyHh+obn+MCRwFPD(*xI?s!kyP#b-384VYC9Z zv!8o~S9v8^oy#Ge83ZehnyZm|fZQQgQ_v1#GE~}oZzNV*si{88Z`8SN!-`~w%xi1dpRVGTqoOo%fD_UhHEBQM?t_luk7w_trAL2z_zx=CV%D{-uMD zB2~KYCy99+6H~ov(Z*H%JQokW;_N$}^M7XJ zQiK%N$I!~=B|2WP1aqr-JzjsY zKM?k$<3tlO9bt~sN!n{j;n?+LsRM6Q$38i|w_f@?OKauqKrE8arIwN&@L7Hi65kQ; z6|^WgYnp6jT7&r92eveafU}q~%j!(VtM?uv2?6OYZVRST@nY@PSMY|LL;I98p;y|R z_?7)?J@d1l7en4U89u}1B*1OdH1OA5zlRK+;$|U)k#pdV3T?mg)|18!N8R;6G+6*YK!|q%aYTb z_Y3Nn2eN9vm02bagL#x~|EZGQlA(w98>5>QB;D(}PhV?OB4kk_|IoQ)zUio0V`rDM z_R%~hN5Ryt>GLMQUS)G1rqksi;H>dNMp^Cos0I;2tna_R_%(_HiQ8bOC0sH2bhtNR z&uIvXgd=?qXHdOJU_-5iT2cVNhq#YO<-%pA<6{!iDu|-)3(g}8S4k$gNfW>;%%S?6 z8pB7_3dt&M`inl2R4Y7I%)9^<8WJ3W zpoce|N5A6DJS07jjxu8**Dw9$;L(aHuC^_hTL#~15s7hHvt<`oqo(&hmjBkvG^n(Gha&i5SpgCvBD+S_JR&+)%L|4Pi^Pwc6Ky6(Fo zTK5E042PATa52%(&Um0^G|)%~r%EpAAZzR?&3&<-9)m60OA6esExFL7f$&r&=mCs@ z^Vk6FWcn(&pDK5aA*{)R7$v`G1r}7&q@y>TYb~&TZ4Gyd=ug%nh4cU&oAf<373K+koLK-3siyr%oy@E9q5k&EK+htE?P;hmGf+gJ; z-|ghzs3QPYl$|4RCFDWqO5-ideOGqgsII=pr~SR7R{s5r1+4kU!69Q&_HD~SKc+== zq%+>ETjT@7GcISXQgd&lsIeZ0pyfgbkXgyk`C7w@lN_2lDnR%dZM?hz6=eAT@(gs2 z7lLGNQ@g=BULM9QN?;9t4kR0fPX>;S7kJ-nK}c_sv+0c&)5wU=R%oXU)M&|$xCT{~ z{Ny{snirBr#d2d@QYBUBRW_SDi!N8qU31gBI}2naTL4g82Va|E=}}zrn47qOGU%sL z;X;5Ud|aa!%!Vy(w_Jh>@P`65bZ~D}=~EA>{=}&uMqK$b7@InaT8Jy$Fb|egzx9B> zS@}q+lzK}Y))4=^OE7o`k5`o>m*xXhgz0R2aEaTdm$|#Pz3rZ+BRx+IChQPl%~gk)lf;TgX+D`$I_OhYdj@Om z8KcJueT9fAC`8tFmk?V^s{1NlWs4<^l*a?pw&HWWy%M)Ot}N%Z+H~{=T2DP{85x41 z^oizXou6u@{q1-f>IURr*aq5DKB&enx}1mc$ughVC>w`6FvSQ9VMR4612xk1@_Vo* zIe5Q_fZgm${JHLHccQr_Z12DZI<67Hm9Ej5n<^nluS9+iEdVFtiZCwYu$2$-OHeAp z&dH@V*)n#3 zAtl8*+d2rPV_Q)0IoD%_rPAOdNz&tNlK1j$J#dM!3KP?&=q^+9Pyq->upcbHAhPpFuB=}`szvg1!ONna&yNELtXbpf(#x70kQmEn?rCy7%f6`~0qXDZp4z+CaL!iojG_I&GU=ufl>!sL6o__9RIQCF<0hM;{2(`KlL<#y* zxJeK2ei!WZw)3VtUk3*HJ(W)84A*k(RA7En$uC0S!}d#@fOYQtXlVnlUq)J@OYafa z`l$83ST}=37SZ`n&BK&$_G>jll?|s1-GZz9+WBbvN*Be=udhs$&io=rXn@n$0LRX4 zUk3S{Mt7{yg_Frh8jHG);d`X{4R@$(rZcN*5PM1h(8&c?H4IMeBPm7Lvg14hKW@Kz z^b71xSGfyOv-crRxmlC-LL*u_*+>WHgM^2VnYZyD(wDhUcN?XSKFd=^e_Vh)x$32G z9ZGPhnvR9bKgKvCJKL_s_)WGc`>IHr@6mZJM+lhmuNz@fA8CHR6@q64C%2h=0%A*S zU@-(3^tCsUDhYV7T0padX!NTq^+=F!XpSU+lgQ9e%^+azeW}5o-16m6tlrn^ zv3RYJ8~NLtx%xG6WiF&(fvgz)wfPZ~_f@{ub$;YfA$HQ2lVVL|@t@T;`rhBs>!t@p z%p@gt;^qe&OBm~i2g?Q{rbbIu?fe$PtUSxMM;WV6_;ac`B|}VIM{}(EQg#3nhMO$? zIzXCqE_)Iq1Wrn19*yWY7A;b&jEt&w29*V(SWW(bbfEkG^u{QHGk%@`DDtaDU05nf zWh28(tJ^$1E(Rko0R`USaosX9t)eY{QVe{u^j$0wMvkfBl~?hiZutnmZ=@z&6e7#v z9W~bYz=O15!z|1pKH&-xM*>3?fgg< zLj>L9qo<4B-xhvwgi0DI?$oSy+~NJKI-Sj?b|wsZr9fG37`l1!im9t)TC(_UJM@~T z;aj`9W)R;Ch-zK#M!ai6stia9)*|i*P>AD7TQxWsv24}tZb>3YHO&D5NopJ_dD|oB zm=Z-o(5mMPy7$dpSs{tai}qDu88uwH)C-gy8#|!H(bR;!40s2*Tg6YzmcdHbnnmrv zZi)Zm&s`s33%lRl>6W_It9Rx{e&7N#hX zWk9|1j6Az^ovS+?CmR7K7w2YgEs3}W3M6CZ@|bKLcRdQ{V`4Ec2FR+lnaj6?DoH%@m78871s{H^E4)G>BPlPT1Jsr8u5b6Tp_k+H zI}Tk*tX4I;13J`0i7$dP0glp!%(KR;v0$p`_6X1UA1_}@%9ok3J28B*>#g3(b-PT; z-fX?PxK`qQlSZ$&YS7(8{c)TN=56oycF{cd=;e{V66F>=-f{?Qo^0l#TmJJ?rkDVc zaJT(h)ti-?m~#06BKMsJr?CycFe^$|E-_jBV0u;W{*IWLMHZWT*N&lT)dB!XUP;4i zs=G%4LeOW=BLOT4>{E50-HW*jU`8ol1^A))UO?bK>b(+5W2YXq|2u?Y?bQ7!c8wo+ZtIDHx4la-0&S8NkDwy z$XW^))ywnNY|oqt`J`O3ec`EY3(eQE?T;aZGkRgC1?{?i&2gF8)WqNF?pr$L_@mL( zNp9OV%g{MLT7vYWZ%I!pzZ88(ld#nO#%cUS{A!DF{LhgS%H>>bAz}k z^XAB5Ca;oI`_C(jgdKr9iE1C2tjg?qS>msKGv6Bb8y$GD=v%gFvRh_-y?F3J&6WXQ zB_>YrnYv}U?ZQ2#-9|0J!q#v>lQvF00iS&OOFG-1YcDz8H>{e6=%+BK4qfsztJ|gF zoP6^pC8{9LId3*5OJ!fVK{LBj`KScBV`tOzXQa>7PdzP0_il1Wmkv>fC9PrvaB=4V zk{^p)nwV>48LjjY^7$q&q%`=P&xl1RugoBPQL+dwEgC?jb>o;ZkouR$k$v zB)l4rzTonDvEOz{UFOb}p%coltT(HBBi9PK1f5P_XQ?M0Wodrcb7mvq9)`Owz2G3T z!Pm%{m>uztjuWkRL1BsvxyvXY@s^zlpvE;an?G=*;8Ck)I2hDW~7sS zooRN&O61W;uITdI{)!Wa59zJ<9$wV^&P$j+3$_Pv`t;Xfl19X&|5(>Zq~%miedu=CQ&{f+mHhFZ%lcSJH;-0Lr9_jg z60y#&gsRY-Wqwg>BuW!e{Vnm=MAC{j6KRb>F0+3TY>T)O4M$^?eQI5&Sjanfrx$b4`v*{`@V4Ghu9tsQk){n@rg6>Tfe%CxG+e%8y{4&fPB zE}4&r+18Zh>zc>EY&g=tKKHCpp!h^ZTZKxjnr)TYQAQiT?L{VT{rr+dj|P{XpM*O$ zQ)IMld|9scxcEvoGf{{|r*}m2_5G_>0}Hx2?X#B#EA9u;D3mfgDunROm&EV3!V|Tk zSIQYLn|d~wFR`4EYD>9QH~5}9_Ehg`m{p$2%=6m=ZgH+%gUMCnTH^s`a^de8N%M;% zql2@tE7iE~3^O7XzI?mAtu^d%Lyi-XW2olm0`chS_R*k9iJ(~2<=z%OYZqN1H==s& zU7mQ!$;%AdEMoR;HdQehloU!TC2gjpU`Q-%uBv_5v%;9*-i=xiw&2t)OqlO4>_m@G zyB}e(S&>tIL)J2w?lGvJ=vsWt>S3TrV&Cuo?C$o)Qa)<~-&f)H6q~N>NJI;PkS(ep z{mgT*qAVi$8r7b^xW7iZ*P!cGRWEG}pOInJM&-fWooEK#iB6&(Y31vi6_)Cj@7kUr;ThW=WC?2o;1P2-Z{*wDa zHU>3cxdd_M{YB|Wt`oH08Su$>vKGm$1=4nn6eMx^&YXF^v`l`RVQb~m#8=5IMoQTPAv1?ya%ITlA zULX3vIj#ONWo_MqcJzeT_Uih!+yH^=YK1s;rl!>OX)qayEE)Hywpu5HyAdc>EGN5vwq3)i~ln=i0NIyj;$Z?rCIVx z13*=C;<_nF5GkQbL&y0Iy+@Rlaz~1Y8s)zA*R;;`PLuECNd?~<>HENw%s(t3uAPP{ z7H%m~2*%UrInU4LGqxEU(;vco!QIvj(wI2)Vg7d!qevM|+--x!5mn+OPZ2~tdZkWr zA9QFjckqj?%tXO~+E>GxKhuxp8OoO*$GDDlvxHV;w^@aio&8%a!-fbL&0>>aQm#mLF!=C$v{Vj&*qqT0SU*$W&K}6rgF?e zoql|sSO}TKq++QD>&)#^3l0g$R$<9v47W57UmqFMkgUUrjz|cY=a{%aiYV&*GXm1d z4k3ZfoTkqZ(+t3ZXai293k3^CfHXk0K+vwKYaPfN6{JohHZ|0@@TpWmpKAcj_fZrt(xH0{IGn2QZOo)9Ka($gI7_hzpHk-uc|dj3-9?Q zi7yLC20BHbDC?D0D}oF%xW?|<`J^X&6;Iz8R1FjGTx#8sSL4eDCNsFhCES_?_4u3~ zU@Wvn%Vab79>c0g83X{C4 zoU`gaN=H5N73y%|5x`TlCGXD;)3MF%io`c^MAg5 zRHw)^6e2hawF-ud0=EY@J~bO82c-m#mZx#fsYR4J4xDz|Z#_KpF~46qC`Nko4qYkV zfZ=gh-_Sw*1+tkUuWoWk5}`Ft((~~Iw{9Q1?`9OuZ$iAf3+O*$t*<+}mp|w2a8YSv zG}4|nl)WCFADEOiwcAbf8Z7q7iq6w}e`?r1Hs_(@(|u zhzL|Z8A=h02)!)f_Ama2~@g>CyFgYa`X>pe6xe?Ii^bG!MRR~mJY5-1as>EPEEBtR04C0 z>%~Bcbu>}=YS)fb6h4(C>HZ@`X3UYJQi4YIV4a}UNauxx5TR@s%-QnEZWtDO* zV`%*OIb~a|V4Wh*i8m|Uqu;vT&?j=p4C-gPy7c;u-)tRPl&SUGq7Cizw)W9Ov= zmm?imvb!ed{`~TDmnZ$z0&^l4pLIEW)=PgQy5=ND8GC0+y53(cD{5um^3is5;Y z1FI3r{8S6~jfGn+MKNLN)OPLBkQd=w+7F&buJ5{^rAwdWjTkjM!o2iGDp4KbCB>Aq(}FudkoZVQfQEbnQMvUm7j?uvH0+6oU$r78QU z=EoO*u41T@@4ef++})s|KI=aFDx1*|la2Kh$ik1G%)Nq1j^WPwy0q{yW1MyFagj0Z zyW9vvwEk`~k%5NvbWy@iZK87!7up@0ggUkK!K&3+nWp%?U|6Q(PqIz|qSyU~vb@NWFtyUeSM2LOj z62&VH2`uu~FSf+%CY=qkZY^UjGh34p9bd~apdWhW=0#waq$nuYa6o7@AD7Idws2l_ zbDK}UdyMRH$GR~&D$gRL$aN&J{Nq|fg+n8XsWY!3aw;~_v;BI0s^dgge?Iw|*@|HK zkVu~1huAgXFUoyNwhU^DDYD7wtt4q!R5>g;S}jc{YE~<3y7$V`$K+(SmLB8KD$`|1 zCQfprzJGFFG}Y70bx5&pR&x8eCUg-cyt}Xx$dh!XAA`}no|9tQk~BO|OYNU!=pGhr zr`?SC{n5hl(N7<_t-C~%t1Kxt%UN2i$)(}XM7{41D&cjyCl9kO22?honJOl%b;_D1 z!#A7pto^KbVa43mn>vD)k0?uZb_Sy<0++=GnI)MI27N#o(jPYL+cYe1eVp4EwbYRWVD*~)G0a$Tj=&d_7q;^*C5m78eBpT#X?j|7Z`#$eOM z!xBYbHq&;UDY9H&R>Ko5h8z60qoeb*-g61&d)+s1BT&jr-m^1NlxVeV^eQc7k&RB& z`NxXu#EX7S(p)Ekd-3+|6i@jJudGmZW`u0FDDwxt^HGKi{_omV$;GQEO;cF6ZHs_C zqGeM8H7_~}P-ojyk4qEO43Y!+Nsx;BTeRCbCWdRM=VSZNWz2X>K}D^`s~vW>^y7OJ zbono=yF~LGvoEE@5w8&@rxJo9MG4=iNNp&Mn(A6iCvT}2$JOo&uf89o@Y1>Uwxy>} zPLu8I`g@y|r`@g=yZf{@Gc!$zhV4y9nZ@V?pLDKhD#n`f9SAGQ%jv0n%cC3_ph?-z z)J&Vui8<%SYuA+4^Tp6Os+MK$-9T=Cu}-O3==_VA7HjA7%ee#nSsxF06uFQ@kepOY z+GFGMGQF!{_2ezll&cJ1%v7I#R;1$1d7i3a!h{F6^pM0 z?x47|mRfpS&s>Ni(%eEK)#)_l%2$DCXCmFoU=_Q$^W)+-&D{9QSL zJ2_?#%~@jIuB6kHkKjen7R&*yI0tFI_`WH*!D{bP(MLOusDp8zFt2d_YTY>OCoLa$ zK?3lmuP+aDNE~4i4XRi7+xR#cy3@%#6(=`23i-&e32GsW_ViuAj2!P4%Q#}1l3Y7? zD`yqn-9CTtZ~ihu(LK-UzCXhLSg_7@o3PONk!I>^_|wfXd|C6ujN@DlbZZmbhF$T? z*_0~R!J$Y$?F_zIy$8=f8vK?vd8wOW9HL%Rj$}82(1i$*W2k!%R{v&=r$6dKam+X& z*oA-)t||YthtpuS>T!L6mCjvxmBBJv#B31Uy18dv4edb|`byxXF7v{Hfc1^rW# zLbO$Wy)1T$`lz?>1uWx+vJ-CHx;619KS%xuKM} z;8CLo1#Z7>BZNdkMHLIYbARUyrIe^kT0PbyK>qG15bJlW`1kH>8B%NduF|;K7;zd_ zBVZofVHnVN{;?Yi^oqT++-FZ1J{Yk;*BaYui)(8;MbB%+F~Mux{~H%DQ2Y@FN{{8u zrvA_gChf7)9@TPtU!uAeehHWok81|0I^Mj0Ok0I8m0iER-3Quzzq!|2z=BxIR5Sp| zZ6T05JfSi#b?^TX(`Fg&3J!l~nSXlUHHH3p3CO?y=e_*?Tf+a|iT=O!$9Vc5jax(< zsBP{6leQdc%LAZ*sxFLdj6C-kldIj1$hWx-2qlnRL>&7+AKX&JM0TdNL5P9as^1jga*Wp-c3?i4B+vFLg2wwZLxa)d_cni z>7+6EUO0sB&B+Ls^Q9yKofuJ-z+Bfeq6o} z;8L4+4-dIcx1F(rz*637uL#zGNd-azX@PlSo#{mW?wbu3FtK?xKT z7c9R0^L_rIe*5R18AOm8-2;jI6Fz;9iRd-pja2Oj?OhsUGWk7X@<7#rSh#%lM;Znq z)rK>#B_XeC5HABUvhcV7!qFBlvuIBh9!JQhpEx-35Ic^%8^OoQY==e4zt|&6KcwkW z4prz2a<4Zqt>&O=RR&R4+g?la{)!H^`Fr6wk4DIqfA+!I&wPZi|0jfQW&hR( zht9t{Pp`M?aTii_`0yx_0}otuLF2bnizC5$HJ+siMa{O3;)?i@BJ&5P%1vY z<042%&kC>y074uzbTa`qEy2L4MF64Vd7A8Fn{P8WPVc&Gukh+GIf=l*B#^>`NkjaW zK4_?}Zw%k)UYI4i|4p#RDKON}mX9Ij8Q^8DBSEUY^S^`BiI;4F){Te-3g08%`Ygac z-uey+kAiF^_*;B`RtFt*hc{V<*qIDPP$OMzOA1eCQSC=~Z<1}0MQL)t^T+hSu(Y&*li+m~M!azT2Mc~ZA z&#B~S@~mqE33U9~Wq6sGlJ)71!b2URj>6l*Q+Tj-SHNTWzTMN^XRMMV2=f&wunB$2 zwHvKWtm2>lMD$bMt%ESPNMH)*Hjkt;O#3OtiyyasK`D|arIiY4#w1fAVz zi&3C02nfjEw?Q*(a5FQ>ul*)NrOUFPBGv;h+)akpy`x1A{gvF(48zkdo@s-kC(JjN zensZD|BtK_0bSTupq(_{EQHk$sjmGl0CW=vA4SBFI_MF23lxK-q7Urt&hG5XQu!IB zEKvwT_7A=wBJ0DqZg3t(I5<`knrM2m#_i4VaLED0?*&on&JU_da$-!Oz^>#qSJ*K0 znw>_#7C6+lr}BtUo}LcqL0XXH1(H8&e9La23-E<9V^6WUGE!%pM@UE*99SVBb^c0^ z)8WT;%#mxBYEn@z0z(vg23+R-W+^JF`*eGx^G&GQiAi^H(fSK;wzzi!ENhRa|WU4b@)QNka)D!-yy_Y&!D_USZ5x*zdU5enY_7V%rz zvop{$2g!rCewlSFv2z7TRV6Sm+EA^^gX`+4@p9vaUQ=6F$xu=1gBQ*gsjY+?LA7fQ zO2-6tv+&;FTt4K&*)|c5QR!r5PE2j2~B`7X1j1@V6vbUjbn|j z1;U~p3_ZAduqG0cIh0w1YWB+}C#A7zq~yr-1<^1-Gqs#*xfW6>Zp=OLv&h~e`#hOf zsoQP<*ebfv6yOp&`zK)G&WJ;#{ccaq5JXniN67b{hc(53#XAxdI{QWPM!c(a{T452!jhg z{ZyVrT?yK--h>>^lhvSa9$w2%RXa1YI@381sn^2NxXW20EV)o!Pvouc3Mx2s1a;69 z7KFR3v`0Axnx5&-wcA~z9OznXzxVNJCCz=8F>7IRX!Z$TXNLt?8*LDD*feQl`d;s$ z5r`F=+Y`ilMt(`bBo4eyugAX9lNp<{*LA}PvF+6XgEMv^Wy-{Y z85gAw3^PkVr;d~3+B~s7fh&g>>{>X4{pPuuxv8FHUIGe81El~;j~y>hA0ZbxLu|B8 z-S$J@ChjFb(|5OxKos>xq+7nq_l%A5L zOZ`=ZBShtOZQ$4pIeG6mmW271vy*EIrifK|UngQ!&KmAOi~5#6 zF@3&^F#X+P-jCVHCTpWXis7i$aB1F-SU>@_-{!!2Tr$D@_Ow^wmn8AQdAoV0-Gqld zTBA{=Vm6QK5(iEM4e0uUG;r9e;pL0*v4f%Yy`dIc^v|%8n+1RP`B@oF>j#B}ti{(A zIC}@I9Ek9k_V$;sOXC>?^&2I?jY&%6^<^5e+Hnz1DFvEU(~EtqENYMU7lN*|5-UV~BZcDv3BWt!{k;lyR-`fBQ|8MAPo?e$95VF@_>DMz%kKfgr0|oc zSJTjvuU609iH;_#X6De4-WP*!Nukjksa1`lZV2Sl294jb6w-vmkcl+8P#D|Axqef> z`DjOYUGQ;^0fAoqaTztr+rvi(vdDM8b%vj%4%;)}nG^-m^17^|%ELp1AL&{hianpA2$@*4qfococZ;c z()Vd6;X?b4tVMQ_Khkr$U6z9uAw*)kz?s{=7~eK3mJ;YoI}5Ze(V2Cf3d`-W8-XXO zZ{GZ&CGTNYH@>Z^qYxw?W<#TKn$94A%hHL!^Iy_1Z+P7clUm~pF&SuA+z z`yMNa)zPgjL!U|FVj%gbPMzdW?78#cWoCD6n?$$U?Yz3$b3OS6gDqN}xSV5@?(w)D z+Li5y&Z&csP*dB+?M4g+FLHiYCE`dOwVE#3J<8((m&KL0Zm+a$lTPoRoL(>Wjmn|t zXptpmj!wme$7IY<=DV(TkvY~9wMR4P&s$v=F(fk=%y&UUth^8~v(75J*&w%0xuW&l zQ_R^&IxVx)$s6_7h2>V~#@-||pew_+RRaT7jq7!nRj;Hk)iqk5M>EB20~_i4AYL*` zAO*@AeWBFX?azev8xEhWein>$zWn~p-KQRX6svT@$Pw5>j#eYpn^yz(e}t}86l;p1By~Xol zSJdc%x&79*{T2PbEQgd8$&v9$I?ueB4Qk8Ufy?;R)pZ7{bpE|`V3k_iNIP)#rs#$c zXKlmk_{wOE*<__|Z{NBwa?Us2zEv|B zy5DEY-798}=X_t8ScJwItyt-nOH%l&2K7~JA3)fXb zJ?g662-B*dxQjKM!<8uVh`#9Ay)ku!>NcX_XN=%t>3%5{u^S{j#4x_WqOP8bU6{C$ z9m_;Hc{_Jh7GsCiA-6x*)ta^3g7#atdh61BD>(HvjAFn6!`|pys|fLuP@=Cl{`x5r zDZ7DQ5x*ITn5KmGmSDePwv@x`AkA2i3nNEp+{7!R3lY_6{^qaZh{ssDH%XT9pGhZ1 z_kG$e;T>;~ZT)MjxxT{u88kJTLroxi)bn<%M8c0(4ND!1elFr_5VkUS<7gF1@pQSI z=p(4`ZZZ3cGbO24R!`rSq1yiE4~Go#6_yQjMGYP8$&{B zzb_@A1Zf$^jbeocb%=YL&;=^CO58mWHT*lJL$jS)m_fpT-Y%cBnhXcWF_F8+wrx|f zK9tL<$s&8ZGVXRt3i+p2a#SS0pQl(?Zf30{?m7Cd7H49XYO)`}Si|Qa-i0|Yio8KX z$xna1f_N&@TM@FgFisFe7lV`A;Ki(j?{OQ4QM`IQ>mTG+v`ewkL_L+3&_`)8-Vkpt z5d2iFOUq=p zIOUr$Z((7eHC>9;Q8tf_|vJ1c*^at8z};LE0Sf zr%}azI`4~Zs`l9`mz-59(v9UGr18>eQe{Y-bkSpQqP|#->g`S8J*NJ4W_^s4a7B^+ zNxj38DrXkWS2~qPu3O*LjY3fNrAJdbp(7i9_MJeTQA7IAcy-c6u}+Dl%Y^m#01Vp+ zYw_FVrOD6Z%cNVrJQ6*?q0n$=FoSY3Jzzh?8s+lmN$wV2t0EdF8PnN>op-lZb=9wc z5q0b*;^|}c=lw1Au+D()L*xKy1jA(f1@4uKs*xjun}bwij&$<%ir}IeC%$Yem{#}K zfwgz;)ltb@_gv{gCs;b_N2gB~yjIl^;6SY&%SoW)F&fUD zu1cItF~#3gZN`)))@}vG-`bZFli>gcY7V2vFQhzu*Vc3!^L-{EnrpkH#g{Xa>g#T8 zb}dWymz-KZY_dfaeJ+lmR&VR5sq{1^V;0@+dGS)Wg9aw02Sd!5SGEv+-@c@RNi8!X zW@2@H8MU1|7R^Y-wK}vL#$O&DcU4dy<2Iy#r zL`#1;Hp6{ezS=Jvq>76EPQ!k4>?QsJWrjWh7poZrZUX958A~W$0fUJB=c!Fmg7jiI zTq_`#gezztVRq+zIuZLt(FNab*C*^33UWo|(J5|rPN$djG$-GZeig@o+3>8s8?9@i z_B-CCSIp%Py-LT4d%uXlN?Fdg<2-PAHi`YY)K7N{9q>|hZ9vzj^xT2^5#E%%bso1W z26=)Lb)ZNYxV0S~w^9?5xP6^vpdn7PLA}#LH)sfzM1TKL+U9iWv~q#5TJ$R*VRO9t z^>>U0h+S{I5qZ!Av+>$dFfX8@dakUXrL_O{n3fgSwqj`0`DCN(xVQW#fB%JQ@43Se zP}%R-pwD_>e9ZCz?})lnDdD%@seZB|DAwM=7!XH*zMMEWT6u94J7R)1k8#3N`S1Rv zVMR`Gx~rxh-V9UqEa+Gla-tuwBCv|FT&N{TWvis@hhO^rzYtdc@rZMBM|RONsIQgwOsbvRLu-OyHSn16kY#{AJ3Z zYG-GC-|@%iyU>`rBqyKHgvhi)sj1Q*{_k95>=1hpM7Ia-L_@zPe{(xdN$v+}Hn`$M zBcV7P>Bs-kW+Sg5V;h-7oCi>@Jo22JE-+t)D}Z`V@DmjAIE@8EuZ2Q@94fY|T<43B zHXNW}G6!1~`|-VV!9T*PFjXS<`GDAn_aTVkvXDLlm;o{9zp_w>U}~^hBkmYpNC%jO z9k9Rq_O5Y1HA*{K!e_|j@3SOu!pML2M^w#7C~B3o=#IGP#|hfZ#s#5|fJ&+a67oUl z4~Hma_YVJ6=r{~s;SwB?bckdUldV#Zkk9R&^@H?HU%dcguQ1pUTbaDNpvp0aI2?m* zYm1WTJilFTCB9KQ@Ib%+zF(@ZHk!b+UjxsIesD^*MwDql1Mv*s&H}k}Pr02@`4N=v zIJAPjKP=Sf1$s##vJ+XERdWZ|E^Wk7Ri zXFlw`EZ}*b`?>Gyx_XkS!_T|el}p=b&o1xzA@1GI-*=bq!a{QCsv4~L`w z^A+@L6ciVN*}>etNWTFG|$Sf>={)i6lR7VX6JUU zFDSyGW}5C<8a&969+M4PuuH-CpAJSlVk!N`{(XpeQN_g~AQzW%6{ie-#~lKtR0~}$ zwU`l=iC8elZbwGgAda4?dOqy0>19TOLSF1Te3@G{-((e4B2gBFGZ=a32kztTFzIY| zjm7ijZs%1RZUl!9q;f-Z`dN4lihBevmH_}i3l7}{cngyooG_kuSg|k$<0d<=#vd6Q zTh-k|qB@bbqO%A&VrN_xxM<=NYq@}AeN&$Ez4tna1pQ1T`Jn0r&kdY~;M=+9mR>n! zD1I7Td5W$0Ez2sLb~=exOShA48|Uxj9f0OLz0O5?W&({SlW=I#JFt2VnO#ZJPwBmS z2O0`zB#vU!Grq-!I(ulX;#J`4*{(5%i=(q`pyUBxAkG!4y|8R-IId?9iQ6 z_(1V@jk>t%3BDYeS*I9@;YD-dhGLqMB=P;bYFbAtUH&lF)`+^~JXVYX(H~mzG zw4#xWfPI&!pvg;ht-X)*V=~g*LFQptz#jUM+k^S z#_I==JC)$7&)U+uptlKpa9Vs{!M;2TsvXX~H%K0+KM=HZYc_IuIn1Z3BZ|D`Atl?) zX$dBNvmn|mwBk>%d~aY^_#SBtV4=?RyXK_35etl+Tdze34EwBAffvv3h{Q9K;78`@ zk7sN2=|F}lWJ;M;tg4?`5eKB+bFjl8yuGA#tvRDybR~ojmhG` zrJs{)e-RSPxX#$_XV2_~lglv_1)ANgq7{Do5tpLW$Q2)T=ogqzy|~7GieOpbI`RGD z%9$!TmB`J}=T)#Xg}>%r?-wQyHvLGcJ16elGT1QrHvQS=^nA4|mcM3cAGHG>V~;g@ zrY|ZMfiTgifD$H<{LbYR;Q`fK_^oZAv=T9H-5&+~PhPA;w3@ofC!`?ld9+2!>*y!1 zxlR@kssza1g7y2J)dv{~PH-vWyr?}0Z3^8=<0ofco{^z2Xh~Vz(vl}1QeP3K@?9>^ zeBXl*J^P^_iEs*@^2_m}9^nPdczEes<~u^%e!Eimhac{c_uL%ssmRc4Mgfst?%+sP z+;0ZE@Tdwd@`jfW#OI#4T$4}LBo4FN8BDX)W&dGf{CVV{&KeS)5d;I%m6muo2tmQF z0(Y^3sh{q0^@e8_)4RR#pFTW)z8|T|-fq@L_F;{ns_Op|*%#%lVu#%zum-wGKr+E5 zf=6wI@9t&~tW~OVsvSGXuhSufJ{oUDk4>G;Tzs~DcB%k23!O)7AscH< zueV|4aBQcIis&-|gAKMb&8$45*D)C&jB;4H_V>O@?&?KgK9za}@7BbZKSBahs8q!7KmI(} z$Z91VyiD9JKHFlJ@sa4GMHbtl0jAETZe;5Y)#QN6R%m~~A^a>%ppkXhQp}?km-Vq>5iM{Y*08JV9a$Dxu&>hK~c8#0=T%U@G9Z%@Z8*}wDbc`Ovjoc{QSCM zR*v`FM(M%RGHk3KfGx9ga`O(h9}#O`MaJGy6dUtstepV=6_2YnfLCyi zYbhDBZjmZwnOoz0R_i4QOAU}WNS^lG9MUiPV5dAFDp zxQ}S|mnV>5K_DilFpPjy(RpPj)$J>=(~G>1sR<7r1Bx7>a~^CubfN4plqBQJ(9nq_ zJ;O-Zt9bv#Y&*)FlP*O&&w*_Wy%cF7P3nEst)y9fVtrAI)Y^H1KxW_$X+Hg}SZ_g% z+_KeYHtYR?X;PxReL8xgXfPdieyOJmORQ$H&dNw0<9h7SU zOhWMN`6KWdFWwXg0U3v09(r+Eb7kFdTXkhh6JwxBaZ@EO4B}mmAv#nNsw#~KMN*<} z>Xf&VPMCN-;JUnGUJkjs7XZiC(V%SWtKS3F2^1?b&{t@}KMM1PMpqtnW`m883&Pw! z;H0Svh#Y_$fW`Q(atdJj3=~dw1ip_@5qB^0D$u;YQ4pb<>=^$BQhbR@Cn% z1{T0EFtAv#{xBB)_RyNa_#4O#XYrV5OvL!DF6^5%s{p4p z&vDd0gD+c*Erv?4H9;n@BwKzf$=eOE)eE4?w*N8_E##1b#?D=(W-mQ{7uwy=Y}Lj@ z4@F%C-bdGd_;w7D7Ctl|b5OW)#^aX$3fD@!61h1~+;W4kTyxkndqOzea6C2C~ zUMj&tRNxLcH|bq3#1}tN75;c2@JG^_36x4vEqOR=Gcc!j8TUO_gizD)8S$XnI4OUW zOfvU7AoY{Nj1l_IhmcV+{68!MIig~oV7Y-4^s9;|4p9e+cbGe4+XcQL1IJOSB(S5y zGs!IaF~@!-G1%;phDv5DEWvm}_J* zDTuoq?giO9&QndI^bVSx^%6MP56yN$y-flc>~zd-i5j2Y%7EWv;9=Jx-sBE=c>@*{ zJ}KW;UqEzKd+cfv=>Xj&HmZWq@Iu_@Wo`)C;TmtWNknB<9!-B1LLo;HhBF@K1KXq( z1_R$`@8!KUVXWb@1lok1aQc&!2KT3sq)R1G_6*F#SM#H-)9meO6@wy2D?v3cIr{8o zt8S}ED0ZDxN{2+!`)Q-&;QIJ&<`Sika?LVw^=537~gbH#aTwG*KlD78Smt^`KT2Ruai)0?D1 z8D-o>zb9ThnbVvD4*nN^D-vg>7J)3%0vo-ViAnt8+?YKKDV!VL4ZtPcT=_sM%8^{E zDu06}9P%e2d6xQ>@t2@Nj>dX2+@ZJX_kY~;#Gc1(9L&U5(YcbPSuqmWDt=?Bc)z0> zb$yJA3GHmDQt$#?gH?9paFn0?4s6B+`>v72nr%C}r3V?4D~SQdfCt{jm00Z(OYvsK zx$-=x^RwkBV|+*(wT3wqYjw1uv6}@-{Z7`LG~^~*F+YF*?p?vkp&|%I8o4;79hN*` zeUN03+nuA@wo~HWUKnXA;5tZMQK{u$+XjjulNfU*EKNGWN_< zlNDEFI0cTI>3|2ER@cn>!Key*Rz5@tRNb|po@$t8<73PGBs3FD7T*I-^ZN`GQcV@4 z3_YPp{w{rtS8e!Kf8_O|1xTx-pvih9^x*eFCFk zkTlRwo6!--z;DgXoYr9uvEuOWlV13&<2xWBG0z^{e6zuON4+a15!pLMm%)L4I%_BA zz`M)BOc+mWQ%<^YOqBK#k$Jnd&t|J~>rR2v+0^b+)Jj`kt{t<*R~ zZH|q}#48cES+8QBhTdz^STb+Py3+OB%&L_Com_ijmJzW8ZXm-smh}^hf%PGN){prJ z6cMIRl1Yk$ib(E)2X{7dU@l=@JxR_DnFM7^acpRgG4`^*O8VlJN75%T8rU3uRh8(? z%{m(_&V12S-7sd8aOIz%z5&f z#HUi(R>rlKxGttQne?_!j6cgZ+J5pf>n1#a~tSM$t^|`AIjLrW0v9$fYJykP4zMGjW%_(3;u^>YF1``A_ zy`ae|;RCLaNRB{RLlnTmPkaHg4>YdDbNfzSBCBIh;Lh4kmg zMzI<4^dq{NvtN9ekiXwg z>(PQY`FmSapA+il!_JqL-N5<9phU9L0yuj6x((HUft06?pl^U?^$dd zJv6SLmU5=Cya)Lvqs$v_Nv-e~+`w!MNE{NaQIdLgFl#f9E)Jtd^;1&78p{li&b?=a zMp8>GTG;iEQ*U~Qn`&m_sho#gJhSZT5HA~h*}X|HLDX1)DGV$ODfW{TU=?dQKw&Icvw>7)nx z$zh(578{s4_?d_?6gCu;V%MdgC#_xXrVrlEg@`cNsa<~e(LV`X(kiwj1KeYhk)KL9 z{ur?#54#07zlif_V}V=klrPg@WpIh|ptC10pwB)rB^pA8MkaH+VOsVhBHdJ7^}l4D2H3uS|?lEyqwF9d5k>) z!G9zDskReKXX$a0iVe&swZGV!C?baXwkMqNqS4|nM}cI zc8@qi=?Q%^(2VIKLo*nu|JG$T4H+F7u& zxn*t6KE*3o&2(B6Kk>#8V?mVh@Q7ggNf=4FY>3X&3$>OfXTHC&q?EG^{Fx-h^C{v1 zH?fa#=1c7fXNc|3HDR4o6viqL!4<~hmMHTBHEOHe_Fx>-%x|} zXw#wA!FT>XN0hma&~2Uq$3QhC34_AVxN2Z;F{i(~@^45>L#mp~h9{N67%A*?=0nGs zi!kNUzaR?M2Y{M4$hC*y#A$XeXm5v(sYr1mkWV zO_^l8pC7Z-$U{GFXUsO;H+M0FT~-eXGGkeBTaH|nVV;nbeE5*-$O~VeY=7>0KgO1A zDnX9(-E$w6JA$Lb!psFv#m)^2WSV=6z^AvPbm8mNGQ*+M{}m5>_osFF^Mm;o{2NE$ zQ3{<<8yLX*3&0=6nbytG&5^DeeP-RUC-QAt_oSi9?m<4BKRx+B{%m>Z505K8m2V3~ za^05mDEOf~^#oGmpifrwNdPidAmcD1DvB)#{nmpin7+0_A(IASGZpfa|Na2;v0(et zj$klwx0u5#_QyfzAt^ezlv;LgXo+0*40(jQ9xG&4R8jc}RtAi9K2LLyy+6z>`+s)y zCV&GUjnUvl6I@3c3@|F#_E4L&Rvk=ZFAu{`^0Vvs2@GzSn3dRnQCNs@t^yU2Nz zZ8^^x{GWDue>Om21>ggy4|9-ouu4N#`6#TAFY*C!L~2=y2f*1j1fKh2ztjH=syeN> zglT8OMcrpv@tK5yqU%W=r`ZqoMV#uutuW>F-okZT41AYweFskIx(gx<@2-PoU|QyI z!Y3dnBXr4oLZ}`T?lxfUwmL>8P&8M^6n&J$e16r%gU4KrsS<;vF+fJ>-Z4A~Bj0$O zm%$KrrwU?xSRQ~eq7~$tOa`_>fjeD|Afe$$N-%U=M#_<;MX(D-4&UC7-05VE)%DgD zeVIa(&Z1xmXcyS$^_3Il`|q@E<|olVv{(M-MfSu%qZ!B7yCTlvf(wcAggNsY-d7&^G>eBKIZ+@%0~vQ3tg%jcp-?RLz9{UJ`sR z2V3hE+=!RR1GiZ61akMOp85nm_h|eNpvm=3=^48ZCL``T5bX+UHB#KpK6%;I2RPAy zgPW`{%!O@X;&$Oi&zo}0XT4T%!h{ED$2s2wSyuZ6G85<*8=s;(10U>TX$plR;@`c2 z*%TX{LsnG8X;YtKS&$>7Sj)L=W?vq2>8qXaBnPjU+W{BitAA#PCPN!wlxQPgO9Rki zT)rYcF9YDTDc>wGzpSwA()_Glvx$1<6%c6PSJ7b5heEg(7L6Hx1OryL8N%E8F<+UY z7|H>l=-OHGckyMWgc5BJK7_^h(5uF&1avWf6-in5>SlalGyKPT;u0`ejvY2Sh31jA zPyq~nMgxRUC(!qh43+jjw)*<^!vu%{0;|FWg!Gp9C1@FK+_3@iHGOJ`F z3LLz4kuSLk09RI$~AN@R>eD{@UMMfriy zKpz0WX)syl%#vLM_;GoK+;;A9TOO)e4vGw?z4k1Gy3rQikFs?A7G#Be0k-Ptg$qv0 zZRN%gzYcr!oRHAW`9y?`Bgq$%W{BQz@}6-QP8lzNMs;lLHDqkAvbD{@IBu}|JOq=P zs`+TVf8sYRGFIY{X_<+dF!&rgi}uO|)zJ+E0X=w+OwF5-cPCh)K0&7?=Wj}p*5L%{ zuTWDY)jnaxUJ}OGM>W5a3*~g~xy{&y0AcW4-jb)dt(UIt42ZV#;$Z5McV@wNEXp0W z1?f$NcCp;jZx{mWJV5kze*$mRHqG>%;0R7w2b@WbRL(8Kxw-F1#qMw&`Y@qDnKNBQ zLiMnVSb+jzeEgi*XPKARb7!EMN=DJ72-@%o2DtjG>c!rFXb?SsELnZF9TGT5uIz!g zpg9(yO6aqIGOEJH2sNpSs+jAoh*sPVN*GbPR$c1&H~>M@aY(2#xe~-KbPjK-^)tR- zw1GVk+mh1(WiL2|F}luNDM+tWs;Q=6r2<~GWzI@K)JLqntqTu(<5}x&m5PIYH z1^6T9=-M6aNeX*?USe_hd24H-Uvd6^rOPq{!_Un^ChF8T*vgMxxj2=a`btHwS2cZBbaMpW+tq|XOjYds4} zCnjzj8!XOq`&AP2vZA(WZ7`^s%>a1eCVdvWvQuQ_3~Wn@ItQsWgD}T5m*a4H%INxt zaIFM^@*} zSzBE)0Ajs=EdwbIY;l`h18lLU?R!oOWDVaQN2-!8meSjtevNhMIs2uQ7 zo;ofYQV!6zc#J`m)=hwX(PnCTEE|{_`<5f-t_H*uD}{pz9oQv)Bj4nW+N%NJ zBa1-BzGOG4D^dO4?1FZNc~q{(5GPng2m%%1>J2aPM{!>%yj1DJAcEL_ zC0#dG1!DB0F_|S|yFT%7e=C+z)=(7B`JY8s0=ctB-uWA{=)Y_yC zruF84X?Tpw+rXrymj4S%W*&vKnTe*PHhWbxnmhRq3nUGLlx(YPLz-@OrNx)$yVF)= z95i49Z$hSyrpI`fUqVs~;kh0tCt^Qq67NIS%XZoGsW%*8m{XzO58BM0r4{HWZP4EE z;qblrZXOYO9uY@l9qix)Q%dpLB)kpsdcA%8?~?i<2*s4VGVThq{IY=snqc$cM2>hp^RxQOW>X<`KYWKWOQl}{8?8dyLgpd!gqc=dGYHIl)Y|g9x&fjXo|09Bty=5`-QxhHCB^!uQF+1H z4Xd4N+E}O+t&{7~i6h36ic$X=s#neV^(-sGy{k#!R=2+6h zYN$6c)>f4l;6;sbUC6$s=P0a&)Q=*IkbFP!j_nOg|zDMN4T zSg*gh0%hIoCz*izkgk~p)k5b$r6)XBmtyMFhohm>J?c}Y_-RkrDog#wp--BASQC^} z>Ze3J5CV2;?VZ$(TD>XKpXG&9kQF(SfK()fxItmY$xQpM;TVFti_B$qG54I(`R{?^ zF*sWq*hiazTFviU+F*e|Em^-$93-&9|~@bWi5)764ZKE6n~s~q4Tofm0z#TVb}N@0%gh+KfIyW(R2b{^pV3` zxE^VN1L|Z%0(7!DK$H6?u~i4iv6&1A3i985Y;VmPgkRei_l1a*yg%vt?hk$dg{vf3 z`zyiTIQekZAi=i}NGn-T2L~;jxc$$6D{h70_-#>wg0BT=W?nJ100MguPgNZI^D_9l zqF54BK4^V+9zeGpRwJlIL}Ja5wLbcMM_Zt8>1B8|Y+!zdVi{VlJu`~9RxJDHFED&y z`ZMJC^ULr5Ny&sYXZW9VPAKZP{q17b|K`pA8l(4r)KZ~;wu|Ne(r?z|1NYS$3UH>T z^~;y^{?n-Wt}Q_N-YDR4`M`-|JnB&fReckwDa{Ii+7|$t=~Qq_7khXECrfU)AvF|b zmH{tmVW1u5T_FopL}Kx=gFZ1InZ=`Oxy&e(Q_OQ+7ddP3=YEY#pk@L2@LvGkhX)L^ z{l3jZ0oFa@x9#-!8KuvlhV++H-{lGHbEGkDgFfbzfIwq4qRN24I2*!I+I^bUh~L-i zgjM98@%ZWK`-7Dva1l>~`I3;nqs|%t7lTB26Gv1~5DODGm@0m|gL!J=IS~MgdQsi; zOSL|$W*}b2HicQDly*3MP6B*4GuGXG@-%R+dZi{|ir3$#62*`56)?3QIuOnA0ar{G zkaXLjVqytGKY`?}KfBrN6`(EV!Xep=SfpkUO`Zq#0WHwa^bS9AyjRZIo^{1Pa}A-E zH@{!b#Ogxj6S{#RD_`DRvJl*hqJ^EP$ny!6d59X|1$P!{=uNjBYXiCNhy+R}ZOnts ze#R-_G19i7WK3t^9V{+pc*3t|zX$T6IlnEO1r^-r(H{GAz7!>z9EPN|qoubrM+cFr zCKQR`n~y#NE%<^N;CFK~&=#VpkA z=cf$IomnUpCf9!i{H_gNBkeenv6?aXiZye%bo3rh-l*6)zLyDm0>#IQjAXrCc9@54 zb@FD-6>=fB*|&jOaNr+_U5}A~T)g`BJ22X4J{ZUkbM& z!FW))r3Abt`CzRqFyvG@w?`p;U3*GZ>=f!)@Pe zU94t%6~cK&0=+|JSR^1V!VFHuEwbO$SQH%^G*xPYow9KZSp%9LI+&-x<&`XBd`im9 z*rg7>$33xcfmV{DqcLQ0ICoo({FNsm!$rdxQ$V{prKzObd9eXDVGm#e`tdd(V&_}# z1z-~*rRl22FTfd8m?+GS9IidLyJX@$=6-Y9+`SzQom=X@aVU$XvV)k5C}#e6wYSaR zYGE0*7(~i$wq9JO7gX}sbnjmfcISft$>hwy{+<#D_p<3IxG8=;(b7X~j7rOx6cV{4 zBqo8WLHkRyp+j(|&)N#--SvAmMntB_bhqt1WI{p4T-v~|6xz7qFLs$2Gfe$rJ}!@j zh8Vuf$dyJxo+TD$4x=tr_mnQ`5ET^_=>-v>E?+bQzu!rckD3?hTzN4N?f9)NjMBp7p*C68au_N)z=-u4>p(y#m~({jEfu2V!jIk<*mA(Rm~LGT^Q~zFTa;A zY%g3ZyoMzqxub**INr>S*{}|l434GrToe_rv8P~_Uk0KMFFb=&>kMUu04xDlD|LG6_DAa94B~g87k?f&jZ<4Cb)d+tB80=$G7)7MmL&dE;GD|QD_WY zP}uO2dP1Pw90pnGFr^UB82Xr%OT)7qwP&w)Fb4B%rXl7V6kazdS<--=SH|R377H5R ziY6Z`&~n@}8VZ5Z@8Ca){S~PjWi&4C>#|IwUJ5XPFQ+v2Dy}KvnUQnkT85c^v2*$w zC-68GFF}RYeqq+fAi*K!jA$D9zb)Cm5Q$Y+kguyR-h$12$qaJh?z1%~ z2t{8WtvOPS7^nvs8BFa{nj$aV+d1PaKZPA&bP`q1jb?|Fu1l53EXyOQC7Ha-9wrRp zr?F9$&Z$wUS&(M8>LI^@m^QA0^SQEX1{nEC`E!I1`+utu1E{Z_LaS5T{%SZErwPN? zra4-V#IHW`tma!^;UtHon;HXwLAFyfb3|@-g|!q%@5|v-swMF!*jzF& zygSglKJ5BH?;I~;*nhegBa|x|$lkn1`#L+c$QpfD1f&zljfe?u14exnA537JIqEZco65wKHCy5q%Vrd)Vma%G2Dqv zZGaBd+eh-DIlsr+&WOo0lF^ObwLZ8=N-$Mpd5j}=`*yoy0~+4}hNPigxu zxZk(_Js*+D!Vo5wpQf?5JJgRSPz_EO{@7!}eCi=yj4<&HYP)G)&Gdet$wXgMdJS}= zB^gsA?%(yvfiKXi~JFYn zjSSyUc2y+d8|iqWP;nV#P@ zDHH{7LbIkNjamVX@!~*1zjf16lh7|1T9#YW{Gb63%Nz2L4j3*~bU-qYeVS*EMiu4FB_zmAQH9cLwn`D>$ zBIo)hh95g}+qBP6>hPQuN$b)V;Cq(GI@T+2s#hgMlL);j`^eZ7y0f8RE;qel`F28W z7)t#?Y2L&~i-sEQ(_en&PDe#uzXc*W<5E{}hQfrVd=q_wmCLO$3l-~M(iYJrE?&?NnuUp;`M(m5-zoAB*u|;cz zbK2-o$zg?VM*i+pVX zry_^CpRPtw6G{eCqCLM_qeb<>e!U<^zC%+7cCztvdwpXMtp76^CDHJJO~PO{pxEz_ zS^I@jiO#{;ZUQTX8VGpu`xmK-wk8foZ78YEw$vVVOtSHLvu%3dR?9uF!H`<}$+d2v z6&kNnO_L3s7#72@Yf584yq-V%P(PcxgBFuocxXl_)9tW~)RTTWZ&3J*)Lmkl$=03L zcdxneRW5*dCD~lwtVmDcaJ+b8&I|9w!3&=A|cK8Unz4c;ww0yyy>%xMguMYM-Dd9&=M2L(jYI|jGC%Wz1H&6m>E=z2qXJ#z^~q=8ry_NB1(vX* zKC+)i&Js7@b(!FTt`1l7Skm?@e{(&!N&)}#W>;4_NX9C(7vxxe5>?_H;(WDm`#_C0 zy%5D5VKJA&K=kKk_5yj_vRDx7`Kn7=8t?tu3d(>?ZoI=CnD={?|3WG9`s)i8tkHgq zb{z@0t&`Ss@^v*DazER3<~%hBtR50;MUsnM39Xb_7itRKQ+eXXk4JKCVTUi3oYSlz z-~UqOS|{sO#7>#O7Y zYs#R&)`iYs1RC)jvSB93*2x2kXfN?PU?MOkGR*FS`++`(b^|DA4ueH`RbWMdIbl&N zWbuw}kkOU`zd3|}pwFJe8okFH5DlFHDwcex4GchCyIkoFBay8TRlEKX!x z|3MmAfBUCD^Ofs@;$al9{M`CvrKJ{_C$7AeWeGhGL6w0Lc~J71tO0my3mfYC1Qcj1 ze`cs~V|+W1nd32j=Mi0|!~c>*6r({?xM&76mFbxe$)Ltv)rBFTmlrz1R3q@jPf+Uo zgkj^KPnf~_Zt!<#H#_TDOaq@MMDB7mXfa1ta(XZqwSh#oiuJ${tIa4cgzKP zNi#U!kjfDR!d)>5!x92?40E2}0pvu&CjwcQYJK!}x zMJfbE+-SIt@y934AA(eo69$GzhS;$)e3&{I@f^r zB;fVU9XLq-ynB^4=z=)IPvF=mIJ#muW&5>3*Ngau6>YyYekS#oJ%z7)Ml7qL+={4L z22;PTjWd8W&rU2Sn#bT%Gxxf1eb!o4~gXT;cZESv2-5TBl;LlX^BIJ>kOukizVTU zl$oF@ZG7BIkWrwS^T~6$(<7}72=O)zECL zeDH&j2qG9-XH|85<5 z9Gz;nBUEdQhjh!;hK+GNaD4>qkAsM#)!XmIqm-!bqqR+It9*nS->o*2heG-ef_Bcz9NO-x%&r*OFU1t zJnFZdE_lP~+Oq-TP80Ga#9$cemtIePZ}X!Ca;*1}wb7@;5RqhS$vopwArO68@8DMTm5( z+{)F0B;~|LJ?N{8VMLvfmkEah2h^b6;>_j%WzaW$1L(+p!-0BhtG_#}uiqV5Yr6!g zVI@G^DOpqxq#gh_hkXuqN&z>pdoPi+sFHS&_vs7~jqYz)PXj2Nhm4oBGYkjYyUjmf<8MLshgh*wF*B1vzEQszl#g6Pgs z*R^_SR4FGrL>iJPM~p`}68@?EdnbMU{1H}$NF)gxOJKgYSkQkVi2W~x#Nm`|h;>4SVEafK32+HVJa^DKYT!1XlsFFcsr9)4)ptE8J-&{z^qa-huu zob~tG;|~4dXE?|H$6mB`06zlCBG^wb9`!(|Am7Xt;N@n%fImf$F*Sd~T1c+fAgGWP zD-p@7`KVRKXSgAot+NN6W;&;fAfu?OimP5U)<{ENI#Ce(s%2ikSR!&~DE`9KhM z4N$9BFxXsJj*d#)`}bn8NahIK3fWU2g#paxFHyw#-EO({Em5pyYQGRCt&@~M9zv$b zU9TL08Cqd!1G0?S8xzocKg1rv*_2IG9nhE(u1c7FjR-}xdkewh+LYgcbhP*+)sA4@ z29_tI_PxJgCT5F*B4Zs&YoR}V*b%GWG?dHiNDV*r_XlD=wtngot`)#~Gvy7YP8~tj ze>R;?S8k_OMQ_xp;iZgc0N)IaqLEOMuU2#_$Z4!gOe{!?fj0Ds^}NM=9_c1cX6o!| zFa<|hn(fzQM@>--ZtT?A$=sY!KqZ@jmT;*%1E3<~!FkvZ+VNeoJXrFU#rm^ z&U7(Tg0+tA6d=tWmTmwnx4=9SF5~!QF7x7GE<~3P#g74U^1Yq=1?oz|PaCy?V*j@- z;e7Of=D_R_Ei-R*WofBsHrWf|egn&%z|Je-uvH!0k9J?5lcQ>*t~li(G1{L0SPJX3 zPanSc4eCA6kbDNB1`IiDyQAC%Aj-OeiE-xj2JUlSuUqK{2S##7xo z3A=~yMyUUA+1ptVU;7v&suO?h{l)HNFy3jn{T|{K{1Hovq#x(zZL&;Y; RgDdD8D#)l_&X6|s`yVw0GJ^mB literal 0 HcmV?d00001 diff --git a/tools/run-kql-script.ps1 b/tools/run-kql-script.ps1 new file mode 100644 index 0000000..231e42c --- /dev/null +++ b/tools/run-kql-script.ps1 @@ -0,0 +1,19 @@ +param( + [Parameter(Mandatory=$true)] + [string]$clusterUri, + + [Parameter(Mandatory=$true)] + [string]$database, + + [Parameter(Mandatory=$true)] + [string]$script +) + +# Check if kusto.cli is in the path +if (-not (Get-Command -Name "kusto.cli" -ErrorAction SilentlyContinue)) { + # Call the install script + $installScriptPath = Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Path -Parent) -ChildPath "install-kusto-cli.ps1" + & $installScriptPath +} + +kusto.cli "${clusterUri}/${database};fed=true" -script:${script} -linemode:false -keeprunning:false