text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: location
using AWS.Compat
using AWS.UUIDs

"""
    associate_tracker_consumer(consumer_arn, tracker_name)
    associate_tracker_consumer(consumer_arn, tracker_name, params::Dict{String,<:Any})

Creates an association between a geofence collection and a tracker resource. This allows
the tracker resource to communicate location data to the linked geofence collection.
Currently not supported — Cross-account configurations, such as creating associations
between a tracker resource in one account and a geofence collection in another account.

# Arguments
- `consumer_arn`: The Amazon Resource Name (ARN) for the geofence collection to be
  associated to tracker resource. Used when you need to specify a resource across all AWS.
  Format example: arn:partition:service:region:account-id:resource-type:resource-id
- `tracker_name`: The name of the tracker resource to be associated with a geofence
  collection.

"""
associate_tracker_consumer(ConsumerArn, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/consumers", Dict{String, Any}("ConsumerArn"=>ConsumerArn); aws_config=aws_config)
associate_tracker_consumer(ConsumerArn, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/consumers", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("ConsumerArn"=>ConsumerArn), params)); aws_config=aws_config)

"""
    batch_delete_geofence(collection_name, geofence_ids)
    batch_delete_geofence(collection_name, geofence_ids, params::Dict{String,<:Any})

Deletes a batch of geofences from a geofence collection.  This action deletes the resource
permanently. You can't undo this action.

# Arguments
- `collection_name`: The geofence collection storing the geofences to be deleted.
- `geofence_ids`: The batch of geofences to be deleted.

"""
batch_delete_geofence(CollectionName, GeofenceIds; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/delete-geofences", Dict{String, Any}("GeofenceIds"=>GeofenceIds); aws_config=aws_config)
batch_delete_geofence(CollectionName, GeofenceIds, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/delete-geofences", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("GeofenceIds"=>GeofenceIds), params)); aws_config=aws_config)

"""
    batch_evaluate_geofences(collection_name, device_position_updates)
    batch_evaluate_geofences(collection_name, device_position_updates, params::Dict{String,<:Any})

Evaluates device positions against the geofence geometries from a given geofence
collection. The evaluation determines if the device has entered or exited a geofenced area,
which publishes ENTER or EXIT geofence events to Amazon EventBridge.  The last geofence
that a device was observed within, if any, is tracked for 30 days after the most recent
device position update

# Arguments
- `collection_name`: The geofence collection used in evaluating the position of devices
  against its geofences.
- `device_position_updates`: Contains device details for each device to be evaluated
  against the given geofence collection.

"""
batch_evaluate_geofences(CollectionName, DevicePositionUpdates; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/positions", Dict{String, Any}("DevicePositionUpdates"=>DevicePositionUpdates); aws_config=aws_config)
batch_evaluate_geofences(CollectionName, DevicePositionUpdates, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/positions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("DevicePositionUpdates"=>DevicePositionUpdates), params)); aws_config=aws_config)

"""
    batch_get_device_position(device_ids, tracker_name)
    batch_get_device_position(device_ids, tracker_name, params::Dict{String,<:Any})

A batch request to retrieve all device positions.

# Arguments
- `device_ids`: Devices whose position you want to retrieve.   For example, for two
  devices: device-ids=DeviceId1&device-ids=DeviceId2
- `tracker_name`: The tracker resource retrieving the device position.

"""
batch_get_device_position(DeviceIds, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/get-positions", Dict{String, Any}("DeviceIds"=>DeviceIds); aws_config=aws_config)
batch_get_device_position(DeviceIds, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/get-positions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("DeviceIds"=>DeviceIds), params)); aws_config=aws_config)

"""
    batch_put_geofence(collection_name, entries)
    batch_put_geofence(collection_name, entries, params::Dict{String,<:Any})

A batch request for storing geofence geometries into a given geofence collection.

# Arguments
- `collection_name`: The geofence collection storing the geofences.
- `entries`: The batch of geofences to be stored in a geofence collection.

"""
batch_put_geofence(CollectionName, Entries; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/put-geofences", Dict{String, Any}("Entries"=>Entries); aws_config=aws_config)
batch_put_geofence(CollectionName, Entries, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/put-geofences", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Entries"=>Entries), params)); aws_config=aws_config)

"""
    batch_update_device_position(tracker_name, updates)
    batch_update_device_position(tracker_name, updates, params::Dict{String,<:Any})

Uploads position update data for one or more devices to a tracker resource. Amazon Location
uses the data when reporting the last known device position and position history.  Only one
position update is stored per sample time. Location data is sampled at a fixed rate of one
position per 30-second interval, and retained for one year before it is deleted.

# Arguments
- `tracker_name`: The name of the tracker resource to update.
- `updates`: Contains the position update details for each device.

"""
batch_update_device_position(TrackerName, Updates; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/positions", Dict{String, Any}("Updates"=>Updates); aws_config=aws_config)
batch_update_device_position(TrackerName, Updates, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/positions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Updates"=>Updates), params)); aws_config=aws_config)

"""
    create_geofence_collection(collection_name, pricing_plan)
    create_geofence_collection(collection_name, pricing_plan, params::Dict{String,<:Any})

Creates a geofence collection, which manages and stores geofences.

# Arguments
- `collection_name`: A custom name for the geofence collection. Requirements:   Contain
  only alphanumeric characters (A–Z, a–z, 0-9), hyphens (-), periods (.), and underscores
  (_).    Must be a unique geofence collection name.   No spaces allowed. For example,
  ExampleGeofenceCollection.
- `pricing_plan`: Specifies the pricing plan for your geofence collection. For additional
  details and restrictions on each pricing plan option, see the Amazon Location Service
  pricing page.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: An optional description for the geofence collection.
- `"PricingPlanDataSource"`: Specifies the plan data source. Required if the Mobile Asset
  Tracking (MAT) or the Mobile Asset Management (MAM) pricing plan is selected. Billing is
  determined by the resource usage, the associated pricing plan, and the data source that was
  specified. For more information about each pricing plan option and restrictions, see the
  Amazon Location Service pricing page. Valid Values: Esri | Here
"""
create_geofence_collection(CollectionName, PricingPlan; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections", Dict{String, Any}("CollectionName"=>CollectionName, "PricingPlan"=>PricingPlan); aws_config=aws_config)
create_geofence_collection(CollectionName, PricingPlan, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("CollectionName"=>CollectionName, "PricingPlan"=>PricingPlan), params)); aws_config=aws_config)

"""
    create_map(configuration, map_name, pricing_plan)
    create_map(configuration, map_name, pricing_plan, params::Dict{String,<:Any})

Creates a map resource in your AWS account, which provides map tiles of different styles
sourced from global location data providers.  By using Maps, you agree that AWS may
transmit your API queries to your selected third party provider for processing, which may
be outside the AWS region you are currently using. For more information, see the AWS
Service Terms for Amazon Location Service.

# Arguments
- `configuration`: Specifies the map style selected from an available data provider.
- `map_name`: The name for the map resource. Requirements:   Must contain only alphanumeric
  characters (A–Z, a–z, 0–9), hyphens (-), periods (.), and underscores (_).    Must be
  a unique map resource name.    No spaces allowed. For example, ExampleMap.
- `pricing_plan`: Specifies the pricing plan for your map resource. For additional details
  and restrictions on each pricing plan option, see the Amazon Location Service pricing page.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: An optional description for the map resource.
"""
create_map(Configuration, MapName, PricingPlan; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/maps/v0/maps", Dict{String, Any}("Configuration"=>Configuration, "MapName"=>MapName, "PricingPlan"=>PricingPlan); aws_config=aws_config)
create_map(Configuration, MapName, PricingPlan, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/maps/v0/maps", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Configuration"=>Configuration, "MapName"=>MapName, "PricingPlan"=>PricingPlan), params)); aws_config=aws_config)

"""
    create_place_index(data_source, index_name, pricing_plan)
    create_place_index(data_source, index_name, pricing_plan, params::Dict{String,<:Any})

Creates a Place index resource in your AWS account, which supports Places functions with
geospatial data sourced from your chosen data provider.  By using Places, you agree that
AWS may transmit your API queries to your selected third party provider for processing,
which may be outside the AWS region you are currently using.  Because of licensing
limitations, you may not use HERE to store results for locations in Japan. For more
information, see the AWS Service Terms for Amazon Location Service.

# Arguments
- `data_source`: Specifies the data provider of geospatial data.  This field is
  case-sensitive. Enter the valid values as shown. For example, entering HERE will return an
  error.  Valid values include:    Esri     Here    For additional details on data providers,
  see the Amazon Location Service data providers page.
- `index_name`: The name of the Place index resource.  Requirements:   Contain only
  alphanumeric characters (A-Z, a-z, 0-9) , hyphens (-), periods (.), and underscores (_).
  Must be a unique Place index resource name.   No spaces allowed. For example,
  ExamplePlaceIndex.
- `pricing_plan`: Specifies the pricing plan for your Place index resource. For additional
  details and restrictions on each pricing plan option, see the Amazon Location Service
  pricing page.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"DataSourceConfiguration"`: Specifies the data storage option for requesting Places.
- `"Description"`: The optional description for the Place index resource.
"""
create_place_index(DataSource, IndexName, PricingPlan; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes", Dict{String, Any}("DataSource"=>DataSource, "IndexName"=>IndexName, "PricingPlan"=>PricingPlan); aws_config=aws_config)
create_place_index(DataSource, IndexName, PricingPlan, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("DataSource"=>DataSource, "IndexName"=>IndexName, "PricingPlan"=>PricingPlan), params)); aws_config=aws_config)

"""
    create_tracker(pricing_plan, tracker_name)
    create_tracker(pricing_plan, tracker_name, params::Dict{String,<:Any})

Creates a tracker resource in your AWS account, which lets you retrieve current and
historical location of devices.

# Arguments
- `pricing_plan`: Specifies the pricing plan for your tracker resource. For additional
  details and restrictions on each pricing plan option, see the Amazon Location Service
  pricing page.
- `tracker_name`: The name for the tracker resource. Requirements:   Contain only
  alphanumeric characters (A-Z, a-z, 0-9) , hyphens (-), periods (.), and underscores (_).
  Must be a unique tracker resource name.   No spaces allowed. For example, ExampleTracker.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: An optional description for the tracker resource.
- `"PricingPlanDataSource"`: Specifies the plan data source. Required if the Mobile Asset
  Tracking (MAT) or the Mobile Asset Management (MAM) pricing plan is selected. Billing is
  determined by the resource usage, the associated pricing plan, and data source that was
  specified. For more information about each pricing plan option and restrictions, see the
  Amazon Location Service pricing page. Valid Values: Esri | Here
"""
create_tracker(PricingPlan, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers", Dict{String, Any}("PricingPlan"=>PricingPlan, "TrackerName"=>TrackerName); aws_config=aws_config)
create_tracker(PricingPlan, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("PricingPlan"=>PricingPlan, "TrackerName"=>TrackerName), params)); aws_config=aws_config)

"""
    delete_geofence_collection(collection_name)
    delete_geofence_collection(collection_name, params::Dict{String,<:Any})

Deletes a geofence collection from your AWS account.  This action deletes the resource
permanently. You can't undo this action. If the geofence collection is the target of a
tracker resource, the devices will no longer be monitored.

# Arguments
- `collection_name`: The name of the geofence collection to be deleted.

"""
delete_geofence_collection(CollectionName; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/geofencing/v0/collections/$(CollectionName)"; aws_config=aws_config)
delete_geofence_collection(CollectionName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/geofencing/v0/collections/$(CollectionName)", params; aws_config=aws_config)

"""
    delete_map(map_name)
    delete_map(map_name, params::Dict{String,<:Any})

Deletes a map resource from your AWS account.  This action deletes the resource
permanently. You cannot undo this action. If the map is being used in an application, the
map may not render.

# Arguments
- `map_name`: The name of the map resource to be deleted.

"""
delete_map(MapName; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/maps/v0/maps/$(MapName)"; aws_config=aws_config)
delete_map(MapName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/maps/v0/maps/$(MapName)", params; aws_config=aws_config)

"""
    delete_place_index(index_name)
    delete_place_index(index_name, params::Dict{String,<:Any})

Deletes a Place index resource from your AWS account.  This action deletes the resource
permanently. You cannot undo this action.

# Arguments
- `index_name`: The name of the Place index resource to be deleted.

"""
delete_place_index(IndexName; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/places/v0/indexes/$(IndexName)"; aws_config=aws_config)
delete_place_index(IndexName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/places/v0/indexes/$(IndexName)", params; aws_config=aws_config)

"""
    delete_tracker(tracker_name)
    delete_tracker(tracker_name, params::Dict{String,<:Any})

Deletes a tracker resource from your AWS account.  This action deletes the resource
permanently. You can't undo this action. If the tracker resource is in use, you may
encounter an error. Make sure that the target resource is not a dependency for your
applications.

# Arguments
- `tracker_name`: The name of the tracker resource to be deleted.

"""
delete_tracker(TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/tracking/v0/trackers/$(TrackerName)"; aws_config=aws_config)
delete_tracker(TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/tracking/v0/trackers/$(TrackerName)", params; aws_config=aws_config)

"""
    describe_geofence_collection(collection_name)
    describe_geofence_collection(collection_name, params::Dict{String,<:Any})

Retrieves the geofence collection details.

# Arguments
- `collection_name`: The name of the geofence collection.

"""
describe_geofence_collection(CollectionName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/geofencing/v0/collections/$(CollectionName)"; aws_config=aws_config)
describe_geofence_collection(CollectionName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/geofencing/v0/collections/$(CollectionName)", params; aws_config=aws_config)

"""
    describe_map(map_name)
    describe_map(map_name, params::Dict{String,<:Any})

Retrieves the map resource details.

# Arguments
- `map_name`: The name of the map resource.

"""
describe_map(MapName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)"; aws_config=aws_config)
describe_map(MapName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)", params; aws_config=aws_config)

"""
    describe_place_index(index_name)
    describe_place_index(index_name, params::Dict{String,<:Any})

Retrieves the Place index resource details.

# Arguments
- `index_name`: The name of the Place index resource.

"""
describe_place_index(IndexName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/places/v0/indexes/$(IndexName)"; aws_config=aws_config)
describe_place_index(IndexName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/places/v0/indexes/$(IndexName)", params; aws_config=aws_config)

"""
    describe_tracker(tracker_name)
    describe_tracker(tracker_name, params::Dict{String,<:Any})

Retrieves the tracker resource details.

# Arguments
- `tracker_name`: The name of the tracker resource.

"""
describe_tracker(TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/tracking/v0/trackers/$(TrackerName)"; aws_config=aws_config)
describe_tracker(TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/tracking/v0/trackers/$(TrackerName)", params; aws_config=aws_config)

"""
    disassociate_tracker_consumer(consumer_arn, tracker_name)
    disassociate_tracker_consumer(consumer_arn, tracker_name, params::Dict{String,<:Any})

Removes the association between a tracker resource and a geofence collection.  Once you
unlink a tracker resource from a geofence collection, the tracker positions will no longer
be automatically evaluated against geofences.

# Arguments
- `consumer_arn`: The Amazon Resource Name (ARN) for the geofence collection to be
  disassociated from the tracker resource. Used when you need to specify a resource across
  all AWS.    Format example:
  arn:partition:service:region:account-id:resource-type:resource-id
- `tracker_name`: The name of the tracker resource to be dissociated from the consumer.

"""
disassociate_tracker_consumer(ConsumerArn, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/tracking/v0/trackers/$(TrackerName)/consumers/$(ConsumerArn)"; aws_config=aws_config)
disassociate_tracker_consumer(ConsumerArn, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("DELETE", "/tracking/v0/trackers/$(TrackerName)/consumers/$(ConsumerArn)", params; aws_config=aws_config)

"""
    get_device_position(device_id, tracker_name)
    get_device_position(device_id, tracker_name, params::Dict{String,<:Any})

Retrieves a device's most recent position according to its sample time.  Device positions
are deleted after one year.

# Arguments
- `device_id`: The device whose position you want to retrieve.
- `tracker_name`: The tracker resource receiving the position update.

"""
get_device_position(DeviceId, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/tracking/v0/trackers/$(TrackerName)/devices/$(DeviceId)/positions/latest"; aws_config=aws_config)
get_device_position(DeviceId, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/tracking/v0/trackers/$(TrackerName)/devices/$(DeviceId)/positions/latest", params; aws_config=aws_config)

"""
    get_device_position_history(device_id, tracker_name)
    get_device_position_history(device_id, tracker_name, params::Dict{String,<:Any})

Retrieves the device position history from a tracker resource within a specified range of
time.  Device positions are deleted after 1 year.

# Arguments
- `device_id`: The device whose position history you want to retrieve.
- `tracker_name`: The tracker resource receiving the request for the device position
  history.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"EndTimeExclusive"`: Specify the end time for the position history in  ISO 8601 format:
  YYYY-MM-DDThh:mm:ss.sssZ. By default, the value will be the time that the request is made.
  Requirement:   The time specified for EndTimeExclusive must be after the time for
  StartTimeInclusive.
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page.  Default value: null
- `"StartTimeInclusive"`: Specify the start time for the position history in  ISO 8601
  format: YYYY-MM-DDThh:mm:ss.sssZ. By default, the value will be 24 hours prior to the time
  that the request is made. Requirement:   The time specified for StartTimeInclusive must be
  before EndTimeExclusive.
"""
get_device_position_history(DeviceId, TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/devices/$(DeviceId)/list-positions"; aws_config=aws_config)
get_device_position_history(DeviceId, TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/devices/$(DeviceId)/list-positions", params; aws_config=aws_config)

"""
    get_geofence(collection_name, geofence_id)
    get_geofence(collection_name, geofence_id, params::Dict{String,<:Any})

Retrieves the geofence details from a geofence collection.

# Arguments
- `collection_name`: The geofence collection storing the target geofence.
- `geofence_id`: The geofence you're retrieving details for.

"""
get_geofence(CollectionName, GeofenceId; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/geofencing/v0/collections/$(CollectionName)/geofences/$(GeofenceId)"; aws_config=aws_config)
get_geofence(CollectionName, GeofenceId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/geofencing/v0/collections/$(CollectionName)/geofences/$(GeofenceId)", params; aws_config=aws_config)

"""
    get_map_glyphs(font_stack, font_unicode_range, map_name)
    get_map_glyphs(font_stack, font_unicode_range, map_name, params::Dict{String,<:Any})

Retrieves glyphs used to display labels on a map.

# Arguments
- `font_stack`: A comma-separated list of fonts to load glyphs from in order of
  preference.. For example, Noto Sans, Arial Unicode.
- `font_unicode_range`: A Unicode range of characters to download glyphs for. Each response
  will contain 256 characters. For example, 0-255 includes all characters from range U+0000
  to 00FF. Must be aligned to multiples of 256.
- `map_name`: The map resource associated with the glyph ﬁle.

"""
get_map_glyphs(FontStack, FontUnicodeRange, MapName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/glyphs/$(FontStack)/$(FontUnicodeRange)"; aws_config=aws_config)
get_map_glyphs(FontStack, FontUnicodeRange, MapName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/glyphs/$(FontStack)/$(FontUnicodeRange)", params; aws_config=aws_config)

"""
    get_map_sprites(file_name, map_name)
    get_map_sprites(file_name, map_name, params::Dict{String,<:Any})

Retrieves the sprite sheet corresponding to a map resource. The sprite sheet is a PNG image
paired with a JSON document describing the offsets of individual icons that will be
displayed on a rendered map.

# Arguments
- `file_name`: The name of the sprite ﬁle. Use the following ﬁle names for the sprite
  sheet:    sprites.png     sprites@2x.png for high pixel density displays   For the JSON
  document contain image offsets. Use the following ﬁle names:    sprites.json
  sprites@2x.json for high pixel density displays
- `map_name`: The map resource associated with the sprite ﬁle.

"""
get_map_sprites(FileName, MapName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/sprites/$(FileName)"; aws_config=aws_config)
get_map_sprites(FileName, MapName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/sprites/$(FileName)", params; aws_config=aws_config)

"""
    get_map_style_descriptor(map_name)
    get_map_style_descriptor(map_name, params::Dict{String,<:Any})

Retrieves the map style descriptor from a map resource.  The style descriptor contains
speciﬁcations on how features render on a map. For example, what data to display, what
order to display the data in, and the style for the data. Style descriptors follow the
Mapbox Style Specification.

# Arguments
- `map_name`: The map resource to retrieve the style descriptor from.

"""
get_map_style_descriptor(MapName; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/style-descriptor"; aws_config=aws_config)
get_map_style_descriptor(MapName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/style-descriptor", params; aws_config=aws_config)

"""
    get_map_tile(map_name, x, y, z)
    get_map_tile(map_name, x, y, z, params::Dict{String,<:Any})

Retrieves a vector data tile from the map resource. Map tiles are used by clients to render
a map. They are addressed using a grid arrangement with an X coordinate, Y coordinate, and
Z (zoom) level.  The origin (0, 0) is the top left of the map. Increasing the zoom level by
1 doubles both the X and Y dimensions, so a tile containing data for the entire world at
(0/0/0) will be split into 4 tiles at zoom 1 (1/0/0, 1/0/1, 1/1/0, 1/1/1).

# Arguments
- `map_name`: The map resource to retrieve the map tiles from.
- `x`: The X axis value for the map tile.
- `y`: The Y axis value for the map tile.
- `z`: The zoom value for the map tile.

"""
get_map_tile(MapName, X, Y, Z; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/tiles/$(Z)/$(X)/$(Y)"; aws_config=aws_config)
get_map_tile(MapName, X, Y, Z, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("GET", "/maps/v0/maps/$(MapName)/tiles/$(Z)/$(X)/$(Y)", params; aws_config=aws_config)

"""
    list_geofence_collections()
    list_geofence_collections(params::Dict{String,<:Any})

Lists geofence collections in your AWS account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional limit for the number of resources returned in a single call.
  Default value: 100
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page.  Default value: null
"""
list_geofence_collections(; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/list-collections"; aws_config=aws_config)
list_geofence_collections(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/list-collections", params; aws_config=aws_config)

"""
    list_geofences(collection_name)
    list_geofences(collection_name, params::Dict{String,<:Any})

Lists geofences stored in a given geofence collection.

# Arguments
- `collection_name`: The name of the geofence collection storing the list of geofences.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page.  Default value: null
"""
list_geofences(CollectionName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/list-geofences"; aws_config=aws_config)
list_geofences(CollectionName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/geofencing/v0/collections/$(CollectionName)/list-geofences", params; aws_config=aws_config)

"""
    list_maps()
    list_maps(params::Dict{String,<:Any})

Lists map resources in your AWS account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional limit for the number of resources returned in a single call.
  Default value: 100
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page. Default value: null
"""
list_maps(; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/maps/v0/list-maps"; aws_config=aws_config)
list_maps(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/maps/v0/list-maps", params; aws_config=aws_config)

"""
    list_place_indexes()
    list_place_indexes(params::Dict{String,<:Any})

Lists Place index resources in your AWS account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional limit for the maximum number of results returned in a single
  call. Default value: 100
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page. Default value: null
"""
list_place_indexes(; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/list-indexes"; aws_config=aws_config)
list_place_indexes(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/list-indexes", params; aws_config=aws_config)

"""
    list_tracker_consumers(tracker_name)
    list_tracker_consumers(tracker_name, params::Dict{String,<:Any})

Lists geofence collections currently associated to the given tracker resource.

# Arguments
- `tracker_name`: The tracker resource whose associated geofence collections you want to
  list.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional limit for the number of resources returned in a single call.
  Default value: 100
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page.  Default value: null
"""
list_tracker_consumers(TrackerName; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/list-consumers"; aws_config=aws_config)
list_tracker_consumers(TrackerName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/trackers/$(TrackerName)/list-consumers", params; aws_config=aws_config)

"""
    list_trackers()
    list_trackers(params::Dict{String,<:Any})

Lists tracker resources in your AWS account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional limit for the number of resources returned in a single call.
  Default value: 100
- `"NextToken"`: The pagination token specifying which page of results to return in the
  response. If no token is provided, the default page is the first page.  Default value: null
"""
list_trackers(; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/list-trackers"; aws_config=aws_config)
list_trackers(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/tracking/v0/list-trackers", params; aws_config=aws_config)

"""
    put_geofence(collection_name, geofence_id, geometry)
    put_geofence(collection_name, geofence_id, geometry, params::Dict{String,<:Any})

Stores a geofence geometry in a given geofence collection, or updates the geometry of an
existing geofence if a geofence ID is included in the request.

# Arguments
- `collection_name`: The geofence collection to store the geofence in.
- `geofence_id`: An identifier for the geofence. For example, ExampleGeofence-1.
- `geometry`: Contains the polygon details to specify the position of the geofence.  Each
  geofence polygon can have a maximum of 1,000 vertices.

"""
put_geofence(CollectionName, GeofenceId, Geometry; aws_config::AbstractAWSConfig=global_aws_config()) = location("PUT", "/geofencing/v0/collections/$(CollectionName)/geofences/$(GeofenceId)", Dict{String, Any}("Geometry"=>Geometry); aws_config=aws_config)
put_geofence(CollectionName, GeofenceId, Geometry, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("PUT", "/geofencing/v0/collections/$(CollectionName)/geofences/$(GeofenceId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Geometry"=>Geometry), params)); aws_config=aws_config)

"""
    search_place_index_for_position(index_name, position)
    search_place_index_for_position(index_name, position, params::Dict{String,<:Any})

Reverse geocodes a given coordinate and returns a legible address. Allows you to search for
Places or points of interest near a given position.  By using Places, you agree that AWS
may transmit your API queries to your selected third party provider for processing, which
may be outside the AWS region you are currently using.  Because of licensing limitations,
you may not use HERE to store results for locations in Japan. For more information, see the
AWS Service Terms for Amazon Location Service.

# Arguments
- `index_name`: The name of the Place index resource you want to use for the search.
- `position`: Specifies a coordinate for the query defined by a longitude, and latitude.
  The first position is the X coordinate, or longitude.   The second position is the Y
  coordinate, or latitude.    For example, position=xLongitude&position=yLatitude .

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: An optional paramer. The maximum number of results returned per request.
  Default value: 50
"""
search_place_index_for_position(IndexName, Position; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes/$(IndexName)/search/position", Dict{String, Any}("Position"=>Position); aws_config=aws_config)
search_place_index_for_position(IndexName, Position, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes/$(IndexName)/search/position", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Position"=>Position), params)); aws_config=aws_config)

"""
    search_place_index_for_text(index_name, text)
    search_place_index_for_text(index_name, text, params::Dict{String,<:Any})

Geocodes free-form text, such as an address, name, city, or region to allow you to search
for Places or points of interest.  Includes the option to apply additional parameters to
narrow your list of results.  You can search for places near a given position using
BiasPosition, or filter results within a bounding box using FilterBBox. Providing both
parameters simultaneously returns an error.   By using Places, you agree that AWS may
transmit your API queries to your selected third party provider for processing, which may
be outside the AWS region you are currently using.  Also, when using HERE as your data
provider, you may not (a) use HERE Places for Asset Management, or (b) select the Storage
option for the IntendedUse parameter when requesting Places in Japan. For more information,
see the AWS Service Terms for Amazon Location Service.

# Arguments
- `index_name`: The name of the Place index resource you want to use for the search.
- `text`: The address, name, city, or region to be used in the search. In free-form text
  format. For example, 123 Any Street.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"BiasPosition"`: Searches for results closest to the given position. An optional
  parameter defined by longitude, and latitude.   The first bias position is the X
  coordinate, or longitude.   The second bias position is the Y coordinate, or latitude.
  For example, bias=xLongitude&bias=yLatitude.
- `"FilterBBox"`: Filters the results by returning only Places within the provided bounding
  box. An optional parameter. The first 2 bbox parameters describe the lower southwest
  corner:   The first bbox position is the X coordinate or longitude of the lower southwest
  corner.   The second bbox position is the Y coordinate or latitude of the lower southwest
  corner.   For example, bbox=xLongitudeSW&bbox=yLatitudeSW. The next bbox parameters
  describe the upper northeast corner:   The third bbox position is the X coordinate, or
  longitude of the upper northeast corner.   The fourth bbox position is the Y coordinate, or
  longitude of the upper northeast corner.   For example,
  bbox=xLongitudeNE&bbox=yLatitudeNE
- `"FilterCountries"`: Limits the search to the given a list of countries/regions. An
  optional parameter.   Use the ISO 3166 3-digit country code. For example, Australia uses
  three upper-case characters: AUS.
- `"MaxResults"`: An optional parameter. The maximum number of results returned per
  request.  The default: 50
"""
search_place_index_for_text(IndexName, Text; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes/$(IndexName)/search/text", Dict{String, Any}("Text"=>Text); aws_config=aws_config)
search_place_index_for_text(IndexName, Text, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = location("POST", "/places/v0/indexes/$(IndexName)/search/text", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Text"=>Text), params)); aws_config=aws_config)


text:
function fibsq16()
#
#  test polynomial suggested by Goedecker
#  square of Fibocacci polynomial
#
    n = 16;
    p = [-1; ones(n)];
    p = conv(p,p);
    z = [-.9349216524104182;
         -.8673161854070643-.3515310211756676*im;
         -.8673161854070643+.3515310211756676*im;
         -.6736211580446324-.6537256870201036*im;
         -.6736211580446324+.6537256870201036*im;
         -.3799784643132753-.8637046142557905*im;
         -.3799784643132753+.8637046142557905*im;
         -.2606735312578153e-1-.9505412093420680*im;
         -.2606735312578153e-1+.9505412093420680*im;
         .3400699024566086-.8988910323302336*im;
         .3400699024566086+.8988910323302336*im;
         .6677317831101087-.7098987824372997*im;
         .6677317831101087+.7098987824372997*im;
         .9066499318552733-.3989926258132711*im;
         .9066499318552733+.3989926258132711*im;
         1.999984739347944];
    z = [z 2*ones(n)]
    p, PolyZeros(z)
end

ext: jl


text:
module TestEntropy
    using Test
    using EcologicalNetworks

    # DIRAC NETWORK
    # only a single interaction

    Ndirac = UnipartiteProbabilisticNetwork([0 0 1; 0 0 0; 0 0 0] / 2)

    inf_decomp_dirac = information_decomposition(Ndirac, norm=true)

    @test inf_decomp_dirac[:D] ≈ 1.0
    @test inf_decomp_dirac[:I] ≈ 0.0
    @test inf_decomp_dirac[:V] ≈ 0.0

    # IDENTITY NETWORK
    # one partner per species, only mutual information is different from 0

    Nid = BipartiteQuantitativeNetwork([1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1])

    inf_decomp_id = information_decomposition(Nid)

    @test inf_decomp_id[:D] ≈ 0.0
    @test inf_decomp_id[:I] ≈ 2.0log2(4.0)
    @test inf_decomp_id[:V] ≈ 0.0

    # UNIFORM NETWORK
    # every species interacts with every other species

    Nunif = BipartiteNetwork(ones(Bool, 10, 6))

    inf_decomp_unif = information_decomposition(Nunif)

    @test convert2effective(inf_decomp_unif[:D]) ≈ 1.0
    @test convert2effective(inf_decomp_unif[:I]) ≈ 1.0
    @test convert2effective(inf_decomp_unif[:V]) ≈ 10 * 6

    # network with assymetric information
    # information is only determined by columns

    Nassym = BipartiteQuantitativeNetwork(ones(5, 1) * rand(1, 7))

    @test mutual_information(Nassym) < 1e-10  # no information between the two variables
    @test diff_entropy_uniform(Nassym; dims=1) < 1e-10
    @test diff_entropy_uniform(Nassym; dims=2) > 0.0
    @test conditional_entropy(Nassym, 2) ≈ entropy(Nassym, dims=1)
end


text:
using DSP
using Polynomials
using Printf

"""
    f1, f2, info = designHBF(fp=0.2, delta=1e-5, debug=0)

Design a half-band filter which can be realized without general multipliers.
The filter is a composition of a prototype and sub-filter.

Input:
- `fp`:     The normalized cutoff frequency of the filter. Due to the symmetry
            imposed by a HBF, the stopband begins at 0.5-`fp`.
- `delta`:  The absolute value of the deviation of the frequency response from
            the ideal values of 1 in the passband and 0 in the stopband.

Output:
- `f1`,`f2`:    The coefficients of the prototype and sub-filters and their
                canonical-signed digit (csd) representation.
- `info`:       A vector containing the following data (only set when `debug`=1):
    - complexity:   The number of additions per output sample.
    - n1,n2:        The length of the `f1` and `f2` vectors.
    - sbr:          The achieved stob-band attenuation (dB).
    - phi:          The scaling factor for the F2 filter.
"""
function designHBF(fp=0.2, delta=1e-5, debug=false)
    worse = 0
    f1_saved = nothing
    f2_saved = nothing
    phi_saved = nothing

    # Try several different values for the fp1 parameter.
    # The best values are usually around .04
    # Surrender if 3 successive attempts yield progressively greater complexity.
    lowest_complexity = Inf
    prev_complexity = Inf
    for fp1 = [.03, .035, .025, .040, .020, .045, .015, .05]
        failed = false

        f1, zetap, phi = designF1(delta, fp1)
        if zetap == 1	# designF1 failed
            failed = true
            if debug
                @printf("designF1 failed at fp1=%f\n", fp1)
            end
        end

        if !failed
            f2 = designF2(fp, zetap, phi)
            n1 = length(f1[1])
            n2 = length(f2[1])
            if n2 == 0  # designF2 failed
                failed = true
                if debug
                    @printf("designF2 failed when zetap=%f, phi=%f\n", zetap, phi)
                end
            end
        end

        if !failed
            f1_csd_size = sum(map(x -> size(x, 2), f1[2]))
            f2_csd_size = sum(map(x -> size(x, 2), f2[2]))
            complexity = f1_csd_size + (2*n1 - 1)*(n2 + f2_csd_size - 1)

            if debug
                msg = @sprintf("%d adders: n1=%d, n2=%d, (fp1=%.2f, zetap=%.3f, phi=%4.2f)",
                                complexity, n1, n2, fp1, zetap, phi)
            else
                msg = ""
            end

            fresp, pbr, sbr = frespHBF([], f1, f2, phi, fp, msg)
            if pbr <= delta && sbr <= delta
                complexity = complexity + sbr
                if complexity < prev_complexity
                    worse = 0
                    if complexity < lowest_complexity
                        lowest_complexity = complexity
                        f1_saved = f1
                        f2_saved = f2
                        phi_saved = phi
                        if debug
                            @printf("%s\n", msg)
                        end
                    end
                else
                    worse = worse + 1
                    if worse > 2
                        break
                    end
                end
                prev_complexity = complexity
            end # if phr <= delta
        end
    end # for fp1

    if isinf(lowest_complexity)
        @printf("Unable to meet the design requirements.\n")
    else
        complexity = floor(lowest_complexity)
        msg = @sprintf("Final Design: %d adders", complexity)
        _, pbr, sbr = frespHBF([], f1_saved, f2_saved, phi_saved, fp, msg)
        n1 = length(f1_saved[1])
        n2 = length(f2_saved[1])
        if debug
            @printf("%s (%d,%d,%.0fdB)\n", msg, n1, n2, dbv(sbr))
        end
        info = [complexity; n1; n2; dbv(sbr); phi_saved]
    end

    return f1_saved, f2_saved, info
end

"""
    f1, zetap, phi = designF1(delta, fp1)

Design the F1 sub-filter of a Saramaki halfband filter.
This function is called by designHBF.

- `f1`:  A 2-tuple of arrays containing the F1 filter coefficents and their CSD
         representation.
- `phi`: The scaling factor for the F2 filter (imbedded in the `f1` coeffs).
"""
function designF1(delta, fp1)
    f1_saved = nothing
    zetap = 0
    phi = 0.0

    passband = exp.(4*pi*im*range(0, fp1, length=100))
    ok = false

    h = []
    n1 = 0
    for i = 1:2:7  # Odd values only
        n1 = i
        if n1 == 1
            h = [0.5, 0.5]
        else
            h = remez(2*n1, [0, 4*fp1], [1], Hz=2)
            if !(abs(sum(h) - 1) < 1e-3)   # remex bug! use least squares instead
                # firls is an open issue in DSP.jl (https://github.com/JuliaDSP/DSP.jl/issues/109)
                error("remez bug not handled yet, try again")
            end
        end
        fresp = abs.(Poly(h)(passband))
        if maximum(abs.(fresp .- 1)) <= delta
            ok = true
            break
        end
    end
    if !ok
        zetap = 1   # Use this as an indication that the function failed.
        return f1_saved, zetap, phi
    end

    # Transform h(n) to a chebyshev polynomial f1(n)
    # Sum(f1(i)*cos(w)^n)|i=1:n1 + Sum(h(n1+i))*cos(n*w))|i=1:n1, n = 2*i-1;
    w = pi * randn(n1)
    cos_w = cos.(w)
    A = zeros(n1, length(w))
    B = zeros(n1)
    for i = 1:n1
        n = 2*i - 1
        A[i,:] = cos_w .^ n
        B = B + h[n1+i] * cos.(n*w)
    end
    f1 = (transpose(B) / A)[:]

    phivecb = []

    # Optimize the quantized version of f1 to maximize the stopband width
    # ( = acos(zetap) )

    zetap = 1
    testPoints = [0; exp10.(range(-2, 0, length=128))] .- 1
    for nsd = 3:8
        # First try the unperturbed filter.
        f1a = f1
        f1b = f1
        for phia = 1 ./ [1; f1]
            phia = phia / 2.0^ceil(log2(abs(phia))) # keep phi in (0.5,1]
            # Try a bunch of coefficients in the current neighborhood,
            # shrinking the neighborhood once 10 successive trial values show no
            # improvement.  If 2 successive shrinkages do no good, try a higher nsd.
            count = 0
            nohelp = 0
            neighborhood = .05
            while neighborhood > 1e-5
                phivec = phia .^ (1:2:(2*n1) .- 1)
                if isempty(phivecb)
                    phivecb = phivec
                end
                f1q = bquantize(f1a .* phivec, nsd)
                F1 = evalF1(f1q[1], testPoints, phia)
                fi = findall(x -> abs(x) > delta, F1)
                zeta = -testPoints[max(fi[1]-1, 1)]
                if zeta < zetap
                    count = 0
                    nohelp = 0
                    zetap = zeta
                    f1b = f1q[1]
                    f1_saved = f1q
                    phi = phia
                    phivecb = phivec
                else
                    count = count + 1;
                end
                if count > 10
                    count = 0
                    neighborhood = neighborhood / 2
                    nohelp = nohelp + 1
                    if nohelp > 2
                        break
                    end
                end
                f1a = f1b./phivecb + neighborhood*(randn(size(f1b)) .- 0.5)
                phia = phia + neighborhood*(rand() - 0.5)
            end
            if zetap < 1    # Found a filter with adequate attn.
                break
            end
        end # for phia ...
        if zetap < 1    # Found a filter with adequate attn.
            break
        end
    end

    return f1_saved, zetap, phi
end

"""
    f2 = designF2(fp, zetap, phi)

Design the F2 sub-filter of a Saramaki halfband filter.
This function is called by designHBF.

subfilter design:
-    1 - delta2' < |F2/`phi`| < 1   for f in [0 `fp`];
-   -1 < |F2/`phi`| < -1 + delta2'  for f in [0.5-`fp`, 0.5];
-    1-delta2' = (1-delta2)/(1+delta2)
"""
function designF2(fp, zetap, phi)
    delta2 = (1 - zetap) / (1 + zetap)

    # determine the minimum order required by the filter
    passband = exp.(im * range(0, 4*pi*fp, length=100))
    nsub = 0
    for i = 3:2:17
        nsub = i
        h2 = remez(nsub+1, [0, 4*fp], [1], Hz=2)
        mag = abs.(Poly(h2)(passband))
        if maximum(abs.(mag .- 1)) < delta2
            break
        end
    end
    n2min = (nsub + 1) / 2

    # Search all n2,nsd pairs, in order of the product n2*(nsd+1)
    # allowing fp to be a variable?
    success = false
    nsdmin = 3
    nsdmax = 6
    for product = (nsdmin+1)*n2min:(nsdmax+1)*n2min
        for nsd = nsdmin:nsdmax
            n2 = product / (nsd + 1)
            if floor(n2) != n2  # Only take integer n2,nsd pairs
                break
            end
            n2 = floor(Int, n2)
            nsub = 2*n2 - 1

            h2 = remez(nsub+1, [0, 4*fp], [1], Hz=2)
            h2 = h2 / (phi * (1 + delta2))  # Adjust the coefficients.
            f2 = bquantize(h2[n2+1:nsub+1], nsd)
            h2 = (1 + delta2) * phi * [f2[1][n2:-1:1]; f2[1]]
            mag = abs.(Poly(h2)(passband))
            if maximum(abs.(mag .- 1)) < delta2
                success = true
                break
            end
        end
        if success
            break
        end
    end
    if !success
        f2 = ([], [])
        q2 = []
    end

    return f2
end

max_stars_repo_name: Mahmoud-Kharsa/DeltaSigma

max_issues_repo_name: Mahmoud-Kharsa/DeltaSigma

max_forks_repo_name: Mahmoud-Kharsa/DeltaSigma


text:
using Distributions: Distribution, Normal
#HACK: Measurements.jl causes weird StackOverFlow error when used with other packages (i.e. Plots, UnicodePlots)
#HACK: not exactly same, but maybe related with https://github.com/PumasAI/Pumas.jl/issues/609
#import Measurements
#using Measurements: Measurement, ±
using Unitful: Quantity

#HACK: define own Measurement just for supporting ± syntax
struct Measurement{T} <: Number
    val::T
    err::T
end

measurement(a::Quantity, b::Quantity) = begin
    u = Unitful.promote_unit(Unitful.unit(a), Unitful.unit(b))
    measurement(deunitfy(a, u), deunitfy(b, u)) * u
end
measurement(a, b) = Measurement(promote(a, b)...)

const ± = measurement
export ±

Base.show(io::IO, m::Measurement) = print(io, "$(m.val) ± $(m.err)")

sample(v::Distribution) = rand(v)
sample(v::Measurement) = rand(Normal(v.val, v.err))
sample(v::Quantity{<:Measurement}) = unitfy(sample(deunitfy(v)), unittype(v))
sample(v) = v


text:
# Earlier versions of this code were tested, but I haven't been able to test the
# latest version due to licensing issues.

using MATLAB

# Monkeypatch the MATLAB versions into the `GuessworkQuantumSideInfo` module
@eval GuessworkQuantumSideInfo begin

    @doc raw"""
        makeR(data)

    Compute a three-dimensional array `R`, such that the third index ranges from
    `y=1:J^k`, and `R[:,:,y]` is described by
    ``
    \sum_{x=1}^J p(x) \sum_{n\in L} c_n μ(n,x,\vec y)  ρ_B^x
    ``
    """
    function makeR(data; do_transpose::Bool)
        @unpack J, K, p, ρBs, c, dB, povm_outcomes = data

        d_out = length(povm_outcomes)

        R_function(g) = sum(c[N(g, x)] * p[x] * ρBs[x] for x in eachindex(p, ρBs))

        R = Array{ComplexF64}(undef, (dB, dB, d_out))
        if do_transpose
            for (y, outcome) in enumerate(povm_outcomes)
                R[:, :, y] .= transpose(R_function(outcome))
            end
        else
            for (y, outcome) in enumerate(povm_outcomes)
                R[:, :, y] .= R_function(outcome)
            end
        end
        R
    end

    function guesswork_MATLAB(
        p,
        ρBs;
        K = length(p),
        c = [1:K..., 10_000],
        dual::Bool = false,
        remove_repetition::Bool = true,
        povm_outcomes = make_povm_outcomes(length(p), K, remove_repetition),
    )
        length(p) == length(ρBs) ||
        throw(ArgumentError("Length of prior and vector of side information must match J"))

        J = length(p)
        dB = size(ρBs[1], 1)
        all(ρB -> size(ρB) == (dB, dB), ρBs) ||
        throw(ArgumentError("All side-information states must be square matrices of the same size"))

        d_out = length(povm_outcomes)

        data = (
            J = J,
            K = K,
            c = c,
            p = p,
            ρBs = ρBs,
            dB = dB,
            d_out = d_out,
            povm_outcomes = povm_outcomes,
        )

        if dual
            R = makeR(data; do_transpose = false)
            mat"""
            dB = double($(dB));
            d_out = double($(d_out));
            R = $(R);
            cvx_begin sdp quiet
            variable Y(dB, dB) hermitian
            dual variable E
            maximize(trace(Y))
            subject to
                E : R >= repmat(Y, [1, 1, d_out])
            cvx_end
            $(Y) = Y;
            $(E) = E;
            $(cvx_optval) = cvx_optval;
            $(cvx_status) = cvx_status;
            """
        else
            R = makeR(data; do_transpose = true)

            mat"""
            dB = double($(dB));
            d_out = double($(d_out));
            R = $(R);
            cvx_begin sdp quiet
            variable E(dB, dB, d_out) hermitian semidefinite
            dual variable Y
            minimize(real( sum( E(:) .* R(:) )))
            subject to
                Y : sum(E, 3) == eye(dB)
            cvx_end
            $(E) = E;
            $(Y) = Y;
            $(cvx_optval) = cvx_optval;
            $(cvx_status) = cvx_status;
            """
        end
        status = Symbol(cvx_status)

        if status != :Solved
            @error "CVX did not successfully solve the problem" status
        end
        Es = [E[:, :, j] for j = 1:d_out]
        return (
            optval = cvx_optval,
            status = status,
            Y = Y,
            Es = Es,
            povm_outcomes = Tuple.(povm_outcomes),
            data...,
        )
    end

end


text:
const R = 8.31446261815324 #J/(mol-K)
export R
const Na = 6.02214076e23 #molecules/mol
export Na
const kB = 1.380649e-23 #J/K
export kB
const F = 96485.33212 #C/mol
export  F
const p_std = 1e5 # Pa
export  p_std
const EPS0 =  8.8541878128e-12 #permittivity of vacuum F/m
export EPS0
const Debye = 3.16227766e-25 # m^(3/2) J^(1/2) #1e-18 cm^3/2 erg^1/2
export Debye
const Angstroms = 1e-10
export Angstroms


text:
using IonBase
using Comonicon.PATH
using Test
using PkgTemplates
using Pkg

@testset "create & release" begin

    @test IonBase.is_version_number("0.1.0")
    @test IonBase.is_version_number("v0.1.0")

    @test_throws ErrorException IonBase.create(PATH.project(IonBase, "test", "dummy2"); user="Roger-luo", template="unknown")

    dummy_project = PATH.project(IonBase, "test", "dummy")
    rm(dummy_project, recursive=true, force=true)
    IonBase.create(dummy_project; user="Roger-luo", template="test")
    project = IonBase.Project(dummy_project, quiet=true)
    @test project.pkg.version == v"0.1.0"
    @test project.path == dummy_project

    IonBase.update_version!(project, "0.2.0")
    @test project.pkg.version == v"0.2.0"
    @test Pkg.Types.read_project(joinpath(dummy_project, "Project.toml")).version == v"0.2.0"

    IonBase.update_version!(project, "patch")
    @test project.pkg.version == v"0.2.1"
    @test Pkg.Types.read_project(joinpath(dummy_project, "Project.toml")).version == v"0.2.1"

    IonBase.update_version!(project, "minor")
    @test project.pkg.version == v"0.3.0"
    @test Pkg.Types.read_project(joinpath(dummy_project, "Project.toml")).version == v"0.3.0"

    IonBase.update_version!(project, "major")
    @test project.pkg.version == v"1.0.0"
    @test Pkg.Types.read_project(joinpath(dummy_project, "Project.toml")).version == v"1.0.0"

end

@testset "search" begin
    @test first(IonBase.search_fuzzy_package("Yao"))[3]["name"] == "Yao"
    @test IonBase.search_exact_package("Yao")[end]["name"] == "Yao"
    @test IonBase.search_exact_package("ASDWXCASDSAS") === nothing
end

@testset "template/comonicon" begin
    test_comonicon = PATH.project(IonBase, "test", "Foo")
    dir = dirname(test_comonicon)
    rm(test_comonicon; recursive=true, force=true)

    t = Template(;
            dir=dir,
            user="me",
            plugins=[
                Readme(;
                    file = IonBase.PATH.templates("command", "README.md"),
                    destination="README.md",
                    inline_badges=false
                ),
                Git(;name="me", email="a@b.c"),
                IonBase.ComoniconFiles(),
            ]
        )

    t(basename(test_comonicon))
    comonicon_toml = joinpath(test_comonicon, "Comonicon.toml")
    @test isfile(comonicon_toml)
    toml = Pkg.TOML.parsefile(comonicon_toml)
    @test toml["name"] == "foo"
    @test toml["install"]["optimize"] == 2
    @test toml["install"]["quiet"] == false
    @test toml["install"]["completion"] == true
    @test isfile(joinpath(test_comonicon, "deps", "build.jl"))
end

@testset "template/comonicon-sysimg" begin
    test_comonicon = PATH.project(IonBase, "test", "Foo")
    dir = dirname(test_comonicon)
    rm(test_comonicon; recursive=true, force=true)

    t = Template(;
        dir=dir,
        user="me",
        plugins=[
            Readme(;
                file = IonBase.PATH.templates("command", "README.md"),
                destination="README.md",
                inline_badges=false
            ),
            Git(;name="me", email="a@b.c"),
            IonBase.ComoniconFiles(),
            IonBase.SystemImage(),
        ]
    )

    t(basename(test_comonicon))
    comonicon_toml = joinpath(test_comonicon, "Comonicon.toml")
    @test isfile(comonicon_toml)
    toml = Pkg.TOML.parsefile(comonicon_toml)
    @test toml["name"] == "foo"
    @test toml["sysimg"]["filter_stdlibs"] == true
    @test toml["sysimg"]["cpu_target"] == "x86-64"
    @test toml["sysimg"]["incremental"] == false
    @test toml["sysimg"]["path"] == "deps/lib"

    @test toml["download"]["repo"] == "Foo.jl"
    @test toml["download"]["host"] == "github.com"
    @test toml["download"]["user"] == "me"
end


text:
using Plots

include("models/Vibron.jl")
include("modules/ClassicalDynamics.jl")

vibronParameters = [0.1, -0.8, 0.7]
energy = 0.1
numTrajectories = 10
PSPoints = 1000

savePath = "d:\\results\\Vibron"

pyplot(size = (1200,1000))
fig = PoincareSection(energy, vibronParameters, numTrajectories; maxPSPoints=PSPoints, verbose=true, sectionPlane=4, min=-sqrt(2.0), max=sqrt(2.0), tolerance=1e-8)
#savefig(fig, savePath * "_PS_E=$(energy)_$vibronParameters.png")

# The following trajectory seems regular, but has an enormous LE
vibronParameters = [0.5,0.5,0.5]
energy = 0.5
initialCondition = [0.0, 1.0203574072397172, -0.9189955424295329, 0.23490092884445612]
#SolveTrajectory(initialCondition, vibronParameters; section=2, verbose=true, showFigures=true)

#initialCondition = [0.0, -0.7862068849266208, 0.7769513368418827, 0.7172308051665519]
#TestTrajectory(initialCondition, vibronParameters)

max_stars_repo_name: PavelStransky/ClassicalDynamics

max_issues_repo_name: PavelStransky/ClassicalDynamics

max_forks_repo_name: PavelStransky/ClassicalDynamics


text:
module CellularAutomata

abstract type AbstractRule end
abstract type AbstractODRule <: AbstractRule end
abstract type AbstractTDRule <: AbstractRule end
abstract type AbstractCA end

struct CellularAutomaton{F,E} <: AbstractCA
    generations::Int
    generation_fun::F
    evolution::E
end

"""
    CellularAutomaton(rule::AbstractODRule, initial_conditions, generations)
    CellularAutomaton(rule::AbstractTDRule, initial_conditions, generations)

Given a cellular automata rule (inluded in the library or provided by the user) returns a CellularAutomaton evolution
with given initial conditions and number of generations. OD indicates one-diomensional cellular automata rules, TD
indicates two-dimensiona cellular automata rules.
"""
function CellularAutomaton(rule::AbstractODRule, initial_conditions, generations)

    evolution = zeros(typeof(initial_conditions[2]), generations, length(initial_conditions))
    evolution[1,:] = initial_conditions

    for i=2:generations
        evolution[i,:] = rule(evolution[i-1,:])
    end

    CellularAutomaton(generations, rule, evolution)

end

function CellularAutomaton(rule::AbstractTDRule, initial_conditions, generations)

    evolution = zeros(typeof(initial_conditions[2]), size(initial_conditions, 1), size(initial_conditions, 2), generations)
    evolution[:, :, 1] = initial_conditions

    for i=2:generations
        evolution[:, :, i] = rule(evolution[:, :, i-1])
    end

    CellularAutomaton(generations, rule, evolution)

end

export CellularAutomaton

include("dca.jl")
export DCA, ECA
include("cca.jl")
export CCA
include("tca.jl")
export TCA

include("life.jl")
export Life

include("measures.jl")
export lempel_ziv

end # module


text:
# tests of various struct types
#
# Lessons:
#  1. we need explicit vectors, not abstract containers
#  2. specialised function makes no difference

module Structs

    using BenchmarkTools
    using InteractiveUtils

    abstract type TestType end

    struct Untyped <: TestType
        a
    end

    struct FixedType  <: TestType
        a :: Vector{Float64}
    end

    struct SemiFixedType1  <: TestType
        a :: Vector{<:Number}
    end

    struct SemiFixedType2  <: TestType
        a :: AbstractArray
    end

    struct SemiParameterisedType{T<:Number}  <: TestType
        a :: AbstractArray{T}
    end

    struct ParameterisedType{ArrayT<:AbstractArray{<:Number}} <: TestType
        a :: ArrayT
    end

    function f(x::TestType)::Real
        s = 0.0
        for i in x.a
          s += i
        end
        s
    end

    function f2( x::ParameterisedType )::Real
        s = 0.0
        for i in x.a
          s += i
        end
        s
    end

    const NA = 10_000
    const nums = rand(NA)

    function do_all()
        type_suite = BenchmarkGroup()

        println( "SemiParameterisedType" )
        # a =
        type_suite[:SemiParameterisedType] = @benchmark f( SemiParameterisedType{Float64}( nums ) )

        println( "ParameterisedType" )
        # b =
        type_suite[:ParameterisedType] = @benchmark f( ParameterisedType{Vector{Float64}}( nums ))

        println( "ParameterisedType(2)" )
        type_suite[:ParameterisedTypeWithSpecialisedFunction] = @benchmark f2( ParameterisedType{Vector{Float64}}( nums ) )
        type_suite
        println( "Untyped" )
        type_suite[:Untyped] = @benchmark f( Untyped( nums ))

        println( "FixedType" )
        type_suite[:FixedType] = @benchmark f( FixedType( nums ))

        println( "SemiFixedType1" )
        type_suite[:SemiFixedType1] =  @benchmark f( SemiFixedType1( nums ))

        println( "SemiFixedType2" )
        type_suite[:SemiFixedType2] = @benchmark f( SemiFixedType2( nums ))
        type_suite
    end

end

Structs.do_all()

max_stars_repo_name: grahamstark/ScottishTaxBenefitModel

max_issues_repo_name: grahamstark/ScottishTaxBenefitModel

max_forks_repo_name: grahamstark/ScottishTaxBenefitModel


text:
struct ZygoteDiffBackend <: AbstractDiffBackend end

function Manifolds._gradient(f, p, ::ZygoteDiffBackend)
    return Zygote.gradient(f, p)[1]
end

function Manifolds._gradient!(f, X, p, ::ZygoteDiffBackend)
    return copyto!(X, Zygote.gradient(f, p)[1])
end

if default_differential_backend() === NoneDiffBackend()
    set_default_differential_backend!(ZygoteDiffBackend())
end


text:
module DecayFit

# Add external packages here

using Random, Distributions, StatsBase
using StructEquality, FFTW

# Add file dependencies here
include("timeaxis.jl")
include("transients.jl")
include("instruments.jl")
include("dkmod.jl")
include("dkmat.jl")
include("simutil.jl")
include("irfsim.jl")
include("dksim.jl")

# Add function exports here
export simulate_irf, simulate_dk

# Write your package code here.

end


text:
# Benchmark the CanopyLayers model

using BenchmarkTools, CanopyLayers, Profile

FT      = Float32;
can     = create_canopy_rt(FT, nLayer=20);
wls     = create_wave_length(FT);
rt_dim  = create_rt_dims(can, wls);
can_rad = create_canopy_rads(FT, rt_dim);
can_opt = create_canopy_opticals(FT, rt_dim);
in_rad  = create_incoming_radiation(wls);
soil    = SoilOpticals{FT}(wls);
angles  = SolarAngles{FT}();
rt_con  = create_rt_cache(FT, rt_dim);
leaves  = [create_leaf_bios(FT, rt_dim) for i in 1:rt_dim.nLayer];
for i in 1:rt_dim.nLayer
    fluspect!(leaves[i], wls);
end

canopy_geometry!(can, angles, can_opt, rt_con);
canopy_matrices!(leaves, can_opt);
short_wave!(can, can_opt, can_rad, in_rad, soil, rt_con);
canopy_fluxes!(can, can_opt, can_rad, in_rad, soil, leaves, wls, rt_con);
SIF_fluxes!(leaves, can_opt, can_rad, can, soil, wls, rt_con, rt_dim);

Profile.clear_malloc_data();

#@btime canopy_geometry!($can, $angles, $can_opt, $rt_con);
#@btime canopy_matrices!($leaves, $can_opt);
#@btime short_wave!($can, $can_opt, $can_rad, $in_rad, $soil, $rt_con);
#@btime canopy_fluxes!($can, $can_opt, $can_rad, $in_rad, $soil, $leaves, $wls, $rt_con);
#@btime SIF_fluxes!($leaves, $can_opt, $can_rad, $can, $soil, $wls, $rt_con, $rt_dim);


text:
function part1(filename::AbstractString)
    lights = zeros(Bool, 1000, 1000)
    for line in eachline(filename)
        instr, x₁, y₁, x₂, y₂ = match(r"(turn on|turn off|toggle) (\d+),(\d+) through (\d+),(\d+)", line)
        rx = parse(Int, x₁):parse(Int, x₂)
        ry = parse(Int, y₁):parse(Int, y₂)
        if instr == "turn on"
            lights[ry, rx] .= true
        elseif instr == "turn off"
            lights[ry, rx] .= false
        elseif instr == "toggle"
            lights[ry, rx] .⊻= true
        else
            throw(ArgumentError("Unrecognized instruction: '$(instr)'"))
        end
    end
    count(lights)
end

function part2(filename::AbstractString)
    lights = zeros(Int, 1000, 1000)
    for line in eachline(filename)
        instr, x₁, y₁, x₂, y₂ = match(r"(turn on|turn off|toggle) (\d+),(\d+) through (\d+),(\d+)", line)
        rx = parse(Int, x₁):parse(Int, x₂)
        ry = parse(Int, y₁):parse(Int, y₂)
        if instr == "turn on"
            lights[ry, rx] .+= 1
        elseif instr == "turn off"
            lights[ry, rx] .= max.(lights[ry, rx] .- 1, 0)
        elseif instr == "toggle"
            lights[ry, rx] .+= 2
        else
            throw(ArgumentError("Unrecognized instruction: '$(instr)'"))
        end
    end
    sum(lights)
end

max_stars_repo_name: stellartux/advent-of-code

max_issues_repo_name: stellartux/advent-of-code

max_forks_repo_name: stellartux/advent-of-code


text:
#
# Update time & ispatch to the right event handler
#
function execute!(state::SimState, params::SimParams, event::Event)::Bool
  @assert state.time <= time(event)  "time for event $event was smaller than current time $(state.time)"
  state.time = time(event)

  event_kind = kind(event)
  was_executed = execute!(event_kind, state, params, event)
  if was_executed
    update!(state.stats, event)
  end
  was_executed
end

function execute!(kind::EventKind, state::SimState, params::SimParams, event::Event)::Bool
  if     OutsideInfectionEvent==kind;           return execute!(Val(OutsideInfectionEvent), state, params, event)
  elseif TransmissionEvent==kind;               return execute!(Val(TransmissionEvent), state, params, event)
  elseif BecomeInfectiousEvent==kind;           return execute!(Val(BecomeInfectiousEvent), state, params, event)
  elseif MildSymptomsEvent==kind;               return execute!(Val(MildSymptomsEvent), state, params, event)
  elseif SevereSymptomsEvent==kind;             return execute!(Val(SevereSymptomsEvent), state, params, event)
  elseif RecoveryEvent==kind;                   return execute!(Val(RecoveryEvent), state, params, event)
  elseif DeathEvent==kind;                      return execute!(Val(DeathEvent), state, params, event)
  elseif HomeTreatmentEvent==kind;              return execute!(Val(HomeTreatmentEvent), state, params, event)
  elseif HomeTreatmentSuccessEvent==kind;       return execute!(Val(HomeTreatmentSuccessEvent), state, params, event)
  elseif GoHospitalEvent==kind;                 return execute!(Val(GoHospitalEvent), state, params, event)
  elseif ReleasedEvent==kind;                   return execute!(Val(ReleasedEvent), state, params, event)
  elseif DetectionEvent==kind;                  return execute!(Val(DetectionEvent), state, params, event)
  elseif TracedEvent==kind;                     return execute!(Val(TracedEvent), state, params, event)
  elseif QuarantinedEvent==kind;                return execute!(Val(QuarantinedEvent), state, params, event)
  elseif QuarantineEndEvent==kind;              return execute!(Val(QuarantineEndEvent), state, params, event)
  elseif ScreeningEvent==kind;                   return execute!(Val(ScreeningEvent), state, params, event)
  else error("unsupported event kind $kind")
  end
  return true
end

function execute!(::Val{ScreeningEvent}, state::SimState, params::SimParams, event::Event)::Bool
  screening!(state, params, event)
  return true
end
#
# transmissions
#

function execute!(::Val{OutsideInfectionEvent}, state::SimState, params::SimParams, event::Event)::Bool
  if Healthy != subjecthealth(state, event) || Free != subjectfreedom(state, event)
    return false
  end

  setsubjecthealth!(state, event, Incubating)

  registerinfection!(state, event)
  incubation_time = progressionof(params, subject(event)).incubation_time
  @assert !ismissing(incubation_time)
  event = Event(Val(BecomeInfectiousEvent), time(event) + incubation_time, subject(event))
  push!(state.queue, event)
  return true
end

function execute!(::Val{TransmissionEvent}, state::SimState, params::SimParams, event::Event)::Bool
  if Healthy != subjecthealth(state, event) # apparently the subject became already infected in some other way
    return false
  end

  source_health = sourcehealth(state, event)
  @assert contactkind(event)==HospitalContact || source_health ∉ SA[Healthy, Incubating, SevereSymptoms, CriticalSymptoms, Dead, Recovered] "infection time exceeds infectability time frame, source is now in state $source_health, the event is $event source progressions are $(progressionof(params, source(event)))"

  # the transmission events are queued in advace, therefore it might be the case that it can not be realized
  # for the transmission to happen both source and subject must be free or both must be staying at home in case
  # the infection takes place inside household

  subject_freedom = subjectfreedom(state, event)
  source_freedom = sourcefreedom(state, event)

  @assert subject_freedom ∉ SA[HomeTreatment, Hospitalized] "a healthy subject should not be in HomeTreatment or Hospital"
  @assert contactkind(event) == HospitalContact || source_freedom ∉ SA[Hospitalized, Released]

  # household contact conditions
  # if it is an infection outside household and either source or subject are closed in home the event can not happen
  if (contactkind(event) != HouseholdContact) && ((HomeTreatment == source_freedom) || (HomeQuarantine == source_freedom) || (HomeQuarantine == subject_freedom))
    return false
  end

  @assert contactkind(event) == HospitalContact || (contactkind(event) == HouseholdContact) || (!isquarantined(state, source(event)) && !isquarantined(state, subject(event))) "the event $event should not be executed because subject state is $(state.individuals[subject(event)]) and source state is $(state.individuals[source(event)])"

  if params.infection_modulation_function !== nothing && !params.infection_modulation_function(state, params, event)::Bool
    return false
  end

  setsubjecthealth!(state, event, Incubating)

  registerinfection!(state, event)

  incubation_time = progressionof(params, subject(event)).incubation_time
  @assert !ismissing(incubation_time)
  push!(state.queue,
    Event(Val(BecomeInfectiousEvent), time(event) + incubation_time, subject(event))
  )
  return true
end

#
# Disease progression
#

function execute!(::Val{BecomeInfectiousEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert Incubating == subjecthealth(state, event)
  subject_id = subject(event)

  sethealth!(state, subject_id, Infectious)

  progression = params.progressions[subject_id]

  severity = progression.severity

  infected_time = time(event) - progression.incubation_time
  if Asymptomatic == severity
    @assert !ismissing(progression.recovery_time)
    push!(state.queue, Event(Val(RecoveryEvent), infected_time + progression.recovery_time, subject_id))
  elseif Mild == severity
    @assert !ismissing(progression.mild_symptoms_time)
    push!(state.queue, Event(Val(MildSymptomsEvent), infected_time + progression.mild_symptoms_time, subject_id))
  elseif Severe == severity || Critical == severity # treat all critical as if they were Severe cases
    if !ismissing(progression.mild_symptoms_time)
      push!(state.queue, Event(Val(MildSymptomsEvent), infected_time + progression.mild_symptoms_time, subject_id))
    else
      push!(state.queue, Event(Val(SevereSymptomsEvent), infected_time + progression.severe_symptoms_time, subject_id))
    end
  else
    @error "Unsupported severity $severity"
  end

  enqueue_transmissions!(state, Val(ConstantKernelContact), event.subject_id, params)
  enqueue_transmissions!(state, Val(HouseholdContact), event.subject_id, params)
  enqueue_transmissions!(state, Val(AgeCouplingContact), event.subject_id, params)
  # hospital transmissions are enqueued in GoHospitalEvent

  detectioncheck!(state, params, subject_id)

  if ishealthcare(params, subject_id) && rand(state.rng) < params.hospital_kernel_params.healthcare_detection_prob
    delay = rand(state.rng, Exponential(params.hospital_kernel_params.healthcare_detection_delay))
    push!(state.queue, Event(Val(DetectionEvent), time(event)+delay, subject_id, OutsideQuarantineDetection))
  elseif(rand(state.rng) < params.mild_detection_prob)
    push!(state.queue, Event(Val(DetectionEvent), time(event)+2, subject_id, OutsideQuarantineDetection))
  end
  return true
end

function execute!(::Val{MildSymptomsEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert Infectious == subjecthealth(state, event)
  setsubjecthealth!(state, event, MildSymptoms)
  subject_id = subject(event)

  progression = progressionof(params, subject_id)
  @assert !ismissing(progression.mild_symptoms_time)

  infection_time = time(event) - progression.mild_symptoms_time

  if Severe == progression.severity || Critical == progression.severity
    @assert !ismissing(progression.severe_symptoms_time)
    @assert infection_time + progression.severe_symptoms_time >= time(event) "$(infection_time + progression.severe_symptoms_time) !>= $(time(event))"
    push!(state.queue, Event(Val(SevereSymptomsEvent), infection_time + progression.severe_symptoms_time, subject_id))
  else
    @assert infection_time + progression.recovery_time > time(event) "next event time $(infection_time + progression.recovery_time) is than current event $event"
    @assert (Mild == progression.severity) "unexpected severity $(progression.severity)"
    push!(state.queue, Event(Val(RecoveryEvent), infection_time + progression.recovery_time, subject_id))
  end

  push!(state.queue, Event(Val(HomeTreatmentEvent), time(event), subject_id), immediate=true) #immediately

  detectioncheck!(state, params, subject_id)

  return true
end

function execute!(::Val{SevereSymptomsEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert subjecthealth(state, event) in SA[Infectious, MildSymptoms]
  setsubjecthealth!(state, event, SevereSymptoms)

  subject_id = subject(event)

  progression = progressionof(params, subject_id)

  #push!(state.queue, RecoveryEvent(time(event)+14, subject(event)))
  event = Event(Val(GoHospitalEvent), time(event), subject(event))
  push!(state.queue, event, immediate=true)  # immediately

  return true
end

function execute!(::Val{RecoveryEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert subjecthealth(state, event) ∉ SA[Recovered, Dead]

  setsubjecthealth!(state, event, Recovered)
  freedom_status = subjectfreedom(state, event)
  if Hospitalized == freedom_status
    push!(state.queue, Event(Val(ReleasedEvent), time(event), subject(event)))
  elseif HomeTreatment == freedom_status
    push!(state.queue, Event(Val(HomeTreatmentSuccessEvent), time(event), subject(event)))
  end
  return true
end

function execute!(::Val{DeathEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert subjecthealth(state, event) ∉ SA[Recovered, Dead]

  setsubjecthealth!(state, event, Dead)
  push!(state.queue, Event(Val(ReleasedEvent), time(event), subject(event)))
  return true
end

#
# freedom events
#

function execute!(::Val{HomeTreatmentEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert MildSymptoms == subjecthealth(state, event)  "subject $(subject(event)) does not have mild symptoms, its state is $(state.individuals[subject(event)]) progression is $(progressionof(params,subject(event)))"
  freedom = subjectfreedom(state, event)
  @assert freedom ∉ SA[Hospitalized, HomeTreatment]

  if Free == freedom
    setsubjectfreedom!(state, event, HomeTreatment)
  else
    @assert HomeQuarantine == freedom
    setsubjectfreedom!(state, event, HomeTreatment)
  end
  return true
end

function execute!(::Val{HomeTreatmentSuccessEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert Recovered == subjecthealth(state, event)
  @assert HomeTreatment == subjectfreedom(state, event) "subject $(subject(event)) was not in HomeTreatment but in $(subjectfreedom(state, event))"
  if isquarantined(state, subject(event))
    setfreedom!(state, subject(event), HomeQuarantine)
  else
    setfreedom!(state, subject(event), Free)
  end
  return true
end

function execute!(::Val{GoHospitalEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert SevereSymptoms == subjecthealth(state, event)
  severity = severityof(params, subject(event))
  @assert severity in SA[Severe, Critical]
  subject_id = subject(event)

  is_from_quarantine = isquarantined(state, subject_id)

  if is_from_quarantine
    quarantine_cancel!(state, subject_id)
  end
  setfreedom!(state, subject_id, Hospitalized)

  enqueue_transmissions!(state, Val(HospitalContact), event.subject_id, params)

  # all hospitalized cases are detected
  if !params.hospital_detections
    return true
  end

  if is_from_quarantine
    push!(state.queue, Event(Val(DetectionEvent), time(event), subject_id, FromQuarantineDetection), immediate=true) # immediately
  else
    push!(state.queue, Event(Val(DetectionEvent), time(event), subject_id, OutsideQuarantineDetection), immediate=true) # immediately
  end
  return true
end

function execute!(::Val{ReleasedEvent}, state::SimState, params::SimParams, event::Event)::Bool
  @assert subjecthealth(state, event) in SA[Dead, Recovered]
  setfreedom!(state, subject(event), Released)
  return true
end

#
# Detection events
#
function execute!(::Val{DetectionEvent}, state::SimState, params::SimParams, event::Event)::Bool
  subject_id = subject(event)
  detection_kind = detectionkind(event)
  if isdetected(state, subject_id)
    return false
  end
  setdetected!(state, subject_id, Detected)
  quarantinehousehold!(state, params, subject_id, include_subject=true)
  if FromQuarantineDetection !== detection_kind
    tracehousehold!(state, params, subject_id, trace_household_connections=true)
  end
  return true
end

function execute!(::Val{TracedEvent}, state::SimState, params::SimParams, event::Event)::Bool
  quarantinehousehold!(state, params, subject(event), include_subject=true)

  for member in householdof(params, subject(event))
    if Undetected != detected(state, member) && UnderObservation != detected(state, member)
      @assert detected(state, member) in SA[TestPending, Detected]
      continue
    end

    if member == source(event) # avoid detection loops
      #@assert Detected == detected(state, member) "member was in state $(state.individual[member])"
      continue
    end

    setdetected!(state, member, TestPending)

    member_health = health(state, member)
    @assert member_health ∉ SA[SevereSymptoms, CriticalSymptoms, Dead] "patient should have already been infected at the hospital"

    if Infectious == member_health || MildSymptoms == member_health
      testing_delay = rand(state.rng, Exponential(params.testing_time))
      push!(state.queue, Event(Val(DetectionEvent), time(event) + testing_delay, member, FromTracingDetection))
    end
  end
  return true
end

function execute!(::Val{QuarantinedEvent}, state::SimState, params::SimParams, event::Event)::Bool
  subject_id = subject(event)
  freedom_state = freedom(state, subject_id)

  is_already_quarantined = isquarantined(state, subject_id)

  if Hospitalized == freedom_state || Released == freedom_state
    @assert !is_already_quarantined "the quarantine should be lifted just before hospitalization"
    return false
  end

  if extension(event)
    @assert Undetected != detected(state, subject_id)
    setfreedom!(state, subject_id, HomeQuarantine)
  elseif Free == freedom_state
    @assert !is_already_quarantined "quarantined cannot be free, but $subject_id is"
    setfreedom!(state, subject_id, HomeQuarantine)
    #setdetected!(state, subject_id, UnderObservation)
  elseif HomeQuarantine == freedom_state
    @assert is_already_quarantined "person's $subject_id state is quarantine therefore isquarantine should return true"
    @assert Undetected != detected(state, subject_id) "the subject should be at least under observation"
  else
    @assert HomeTreatment == freedom_state "bad freedom status detected = $freedom_state"
  end

  detection_state = detected(state, subject_id)
  if Undetected == detection_state
    setdetected!(state, subject_id, UnderObservation)
  end

  quarantine_advance!(state, subject_id, +1)  # increase quarantine level
  push!(state.queue, Event(Val(QuarantineEndEvent), time(event)+params.quarantine_length, subject_id))

  return !is_already_quarantined
end

function execute!(::Val{QuarantineEndEvent}, state::SimState, params::SimParams, event::Event)::Bool
  subject_id = subject(event)
  @assert Undetected != detected(state, subject_id) "subject $subject_id must be at least under observation since the quarantine is ending"

  subject_freedom = freedom(state, subject_id)

  if  (Hospitalized == subject_freedom) || (Released == subject_freedom)
    # false event as quarantine should have been removed before hospitalization
    @assert !isquarantined(state, subject_id) "subject in state $subject_freedom detected in quarantine"
    return false
  end

  quarantine_advance!(state, subject_id, -1)  # reduce quarantine level
  if isquarantined(state, subject_id)
    return false  # ignore event, the quarantine should last longer
  end

  subject_health = health(state, subject_id)

  if Infectious == subject_health || MildSymptoms == subject_health
    quarantinehousehold!(state, params, subject_id, include_subject=true, extension=true)
    return false
  end

  @assert subject_health in SA[Healthy, Incubating, Recovered] "subject $subject_id must be in hospital hence not quarantined state = $(individualstate(state, subject_id))"
  setfreedom!(state, subject_id, Free)

  return true
end

#
# Quarantine and backtracing helpers
#

function detectioncheck!(state::SimState, params::SimParams, person_id::Integer)
  now = state.time
  if Undetected != detected(state, person_id)
    if isquarantined(state, person_id)
      push!(state.queue, Event(Val(DetectionEvent), now, person_id, FromQuarantineDetection), immediate=true) # immediately
    else
      push!(state.queue, Event(Val(DetectionEvent), now, person_id, OutsideQuarantineDetection), immediate=true) # immediately
    end
  end
end

function quarantinehousehold!(state::SimState, params::SimParams, subject_id::Integer; include_subject::Bool, extension::Bool=false)
  for member in householdof(params, subject_id)
    if !include_subject && (member == subject_id)
      continue
    end

    member_freedom = freedom(state, member)

    if (Hospitalized == member_freedom) || (Released == member_freedom)
      continue
    end
    @assert member_freedom in SA[Free, HomeTreatment, HomeQuarantine]
    push!(state.queue, Event(Val(QuarantinedEvent), state.time, member, extension), immediate=true) #immediately
  end
  nothing
end

function tracehousehold!(state::SimState, params::SimParams, subject_id::Integer; trace_household_connections::Bool)
  for member in householdof(params, subject_id)
     backtrace!(state, params, member, trace_household_connections=trace_household_connections)
     forwardtrace!(state, params, member, trace_household_connections=trace_household_connections)
  end
  nothing
end

function backtrace!(state::SimState, params::SimParams, person_id::Integer; trace_household_connections::Bool)
  current_time = time(state)

  event = backwardinfection(state, person_id)
  backward_id = source(event)

  if NoContact == contactkind(event) || OutsideContact == contactkind(event)
    @assert 0 == backward_id
    return
  end

  if !trace_household_connections && (HouseholdContact == contactkind(event))
    return
  end

  @assert 0 != backward_id "backward_id=$backward_id infection=$event"
  if isdetected(state, backward_id)
    return
  end

  if uses_phone_tracing(params, person_id) &&
      uses_phone_tracing(params, backward_id) &&
      rand(state.rng) < params.phone_tracing_params.detection_prob
      detection_delay = rand(state.rng, Exponential(params.phone_tracing_params.detection_delay))
    push!(state.queue, Event(Val(TracedEvent), current_time + detection_delay, backward_id, person_id, PhoneTraced))
  elseif rand(state.rng) < params.backward_tracing_prob
    detection_delay = rand(state.rng, Exponential(params.backward_detection_delay))
    push!(state.queue, Event(Val(TracedEvent), current_time + detection_delay, backward_id, person_id, ClassicalTraced))
  end
  nothing
end

function forwardtrace!(state::SimState, params::SimParams, person_id::Integer; trace_household_connections::Bool)
  current_time = time(state)

  # handle all outgoing infections
  for infection in forwardinfections(state, person_id)

    contact_kind = contactkind(infection)
    @assert contact_kind ∉ SA[OutsideContact, NoContact]

    forward_id = subject(infection)

    health_state = health(state, forward_id)
    @assert Healthy != health_state

    if !trace_household_connections && (HouseholdContact == contact_kind)
      continue
    end

    if isdetected(state, forward_id)
      # the check for detected should be enough for avoiding loops and multiple checks of the same person
      # - in case there are multiple backtracing processes at the same time it does not affect the chances of being tested positively
      # - here we are looking for the contacts and all the contacts  already are or were infected
      # - only true infections are stored hence no one will be forward traced twice anyway
      # it is just the chance of being detected which becomes larger if multiple backtracings are leading to the same person
      continue
    end

    # in very rare circumstances these asserts are actually not true - if the backtracing comes in exactly between hospitalization and detection
#    @assert health_state ∉ SA[SevereSymptoms, CriticalSymptoms, Dead] "the forward $forward_id should have already been detected at the hospital but his health is $health_state"
    freedom_state = freedom(state, forward_id)
#    @assert freedom_state ∉ SA[Hospitalized, Released] "the forward $forward_id should have already been detected at the hospital but he is $freedom_state"

    if uses_phone_tracing(params, person_id) &&
        uses_phone_tracing(params, forward_id) &&
        rand(state.rng) < params.phone_tracing_params.detection_prob
        detection_delay = rand(state.rng, Exponential(params.phone_tracing_params.detection_delay))
      push!(state.queue, Event(Val(TracedEvent), current_time + detection_delay, forward_id, person_id, PhoneTraced))
    elseif rand(state.rng) < params.forward_tracing_prob
      detection_delay = rand(state.rng, Exponential(params.forward_detection_delay))
      push!(state.queue, Event(Val(TracedEvent), current_time + detection_delay, forward_id, person_id, ClassicalTraced))
    end

  end
  nothing
end