diff --git a/api/jsonschema/schema.json b/api/jsonschema/schema.json index f7a84c3d3f55..96b0025dd419 100644 --- a/api/jsonschema/schema.json +++ b/api/jsonschema/schema.json @@ -6299,6 +6299,10 @@ "configMapKeyRef": { "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapKeySelector", "description": "ConfigMapKeyRef is configmap selector for Semaphore configuration" + }, + "rebalanceKey": { + "description": "RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key", + "type": "string" } }, "type": "object" diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 06d90e376c70..1ffee45ebc5d 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -10230,6 +10230,10 @@ "configMapKeyRef": { "description": "ConfigMapKeyRef is configmap selector for Semaphore configuration", "$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapKeySelector" + }, + "rebalanceKey": { + "description": "RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key", + "type": "string" } } }, diff --git a/config/config.go b/config/config.go index ec970f0286aa..72b000c38228 100644 --- a/config/config.go +++ b/config/config.go @@ -281,6 +281,14 @@ const ( TemplateReferencingSecure TemplateReferencing = "Secure" ) +// SemaphoreStrategy determines how locks are distributed to pending lock holders. +type SemaphoreStrategy string + +const ( + SemaphoreStrategyDefault SemaphoreStrategy = "default" + SemaphoreStrategyRebalanced SemaphoreStrategy = "rebalanced" +) + func (req *WorkflowRestrictions) MustUseReference() bool { if req == nil { return false diff --git a/docs/executor_swagger.md b/docs/executor_swagger.md index 61201056eb21..04533b705059 100644 --- a/docs/executor_swagger.md +++ b/docs/executor_swagger.md @@ -4216,6 +4216,7 @@ Note that this field cannot be set when spec.os.name is windows. | Name | Type | Go type | Required | Default | Description | Example | |------|------|---------|:--------:| ------- |-------------|---------| | configMapKeyRef | [ConfigMapKeySelector](#config-map-key-selector)| `ConfigMapKeySelector` | | | | | +| rebalanceKey | string| `string` | | | RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key | | diff --git a/docs/fields.md b/docs/fields.md index d37bc7253e9c..305b521c66be 100644 --- a/docs/fields.md +++ b/docs/fields.md @@ -2346,6 +2346,7 @@ SemaphoreRef is a reference of Semaphore | Field Name | Field Type | Description | |:----------:|:----------:|---------------| |`configMapKeyRef`|[`ConfigMapKeySelector`](#configmapkeyselector)|ConfigMapKeyRef is configmap selector for Semaphore configuration| +|`rebalanceKey`|`string`|RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key| ## ArtifactLocation diff --git a/docs/proposals/rebalanced-semaphore.md b/docs/proposals/rebalanced-semaphore.md new file mode 100644 index 000000000000..4a8df0240100 --- /dev/null +++ b/docs/proposals/rebalanced-semaphore.md @@ -0,0 +1,118 @@ +# Rebalanced Semaphore Strategy + +## Introduction + +In some situations where Argo is orchestrating a service with many end users, it may be the case that we want these users to have equal access to a particular resource. As number of concurrent users increases or decreases, we want Argo to know each users' constantly-changing lock quota. + +One example could be distribution of a finite number of software licenses, where a Running node holds a single license for the duration of its execution. + +This feature extends the behavior of Argo's [semaphore](https://github.com/argoproj/argo-workflows/blob/master/docs/synchronization.md) so that, in addition to specifying a rate limit for the number of locks available, the Argo user can specify a `rebalanceKey` directly in the Workflow file. + +All Workflows sharing the same `rebalanceKey` will have access to ${ 1 / total # distinct `rebalanceKey`s} of this semaphore's rate limit. + +_Argo users who do not use this feature are implicitly using the already-existing [default](https://github.com/argoproj/argo-workflows/blob/master/docs/synchronization.md) strategy._ + +### Example + +Suppose we have the following: + +* Semaphore S with limit 55 +* Workflow A with 100 child nodes all vying for S with `rebalanceKey` J +* Workflow B with 100 child nodes all vying for S with `rebalanceKey` J +* Workflow C with 500 child nodes all vying for S with `rebalanceKey` K + +Suppose A, B, and C are submitted, in that order. Then: + +* There are two distinct `rebalanceKey`s J and K (that are either pending or held) +* Because A was submitted before B, and A and B both have `rebalanceKey` J, all of A's child nodes will receive a lock from S before any of B's. +* Because A was submitted before B and C, A _could_ briefly receive all of the locks because none of B or C's resources were added to the queue of pending lock holders. +* The list of resources holding a lock from S should quite quickly converge to a list where 27 of the holders are from A and 26 are from B (or vice versa). This is the steady state until A (or C) completes. + +Suppose A and B complete, but C is still running. Then: + +* C will have access to all 55 locks. + +## User guide + +### Configuration + +Suppose we want to configure some semaphore named "template" to use the rebalanced strategy. First configure the semaphore with a limit, as described in the [synchronization](https://github.com/argoproj/argo-workflows/blob/master/docs/synchronization.md) documentation. Then, create a new property with the same name, and append `-strategy` to the end of it. This property currently supports "rebalanced" and "default". + +The final config file should look something like: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: my-config +data: + template: "5" + template-strategy: "rebalanced" +``` + +Note that the strategy should be added to the same config file that the limit is defined in. + +The workflow controller should be restarted if a change in strategy takes place. This is because the strategy is fixed when the controller in initialized. + +The controller will output logs that explain which strategies were chosen by each semaphore. + +Note that semaphores not included in `semaphoreStrategies` will use the [default](https://github.com/argoproj/argo-workflows/blob/master/docs/synchronization.md) strategy. Not specifying the `semaphoreStrategies` key will configure all semaphores to use the default strategy. + +To use the rebalanced semaphore, a user should (but is not required to) specify a `rebalanceKey` inside of the `synchronization.semaphore` property: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: rebalance-key-test- +spec: + arguments: + parameters: + - name: rebalancekey + value: "example-key-123" + entrypoint: rebalance-key-test-entrypoint + templates: + - name: rebalance-key-test-entrypoint + steps: + - - name: generate + template: gen-number-list + - - name: synchronization-acquire-lock + template: acquire-lock + withParam: "{{steps.generate.outputs.result}}" + - name: gen-number-list + script: + image: python:alpine3.6 + command: [python] + source: | + import json + import sys + json.dump([i for i in range(0, 15)], sys.stdout) + - name: acquire-lock + synchronization: + semaphore: + configMapKeyRef: + name: my-config + key: template + rebalanceKey: "{{workflow.parameters.rebalancekey}}" + container: + image: alpine:latest + command: [sh, -c] + args: ["echo acquired lock; sleep $((20 + RANDOM % 11));"] +``` + +After setting up your config file as described above, run this workflow two times, each time using a different `rebalanceKey`: + +Submit a workflow with `user-000`: `argo submit rebalance-key-test.yaml -p 'rebalancekey=user-000'` + +Submit a workflow with `user-001`: `argo submit rebalance-key-test.yaml -p 'rebalancekey=user-001'` + +At first, the workflow from the first submission should use both available locks. After one pod completes, notice that lock allocation converges so that each workflow has constant access to 1 lock until one workflow finishes entirely, at which point the remaining workflow has access to both locks. + +### Assumptions + +The following is a list of operational assumptions that a rebalanced semaphore user should understand before deciding to use this feature: + +* Workflow and Config file formats are backward compatible, meaning that existing workflows that do not want to use the rebalanced strategy need to make no changes. +* A single workflow _can_ use many distinct semaphores using the rebalanced strategy. +* A single workflow _can not_ use one particular semaphore with two `rebalanceKey`s, even if they are used in two distinct locations within that workflow. +* A semaphore that is using a semaphore with the rebalanced strategy will ignore priority diff --git a/examples/rebalance-key.yaml b/examples/rebalance-key.yaml new file mode 100644 index 000000000000..2c23ff609a3a --- /dev/null +++ b/examples/rebalance-key.yaml @@ -0,0 +1,88 @@ +# Suppose we have some semaphore with a limit of 4 that we want to share equally amongst lock requesters +# with the same rebalanceKey (see below in this example) +# +# We'd first set up the semaphore test-scale with a limit, as described in +# [synchronization](https://github.com/argoproj/argo-workflows/blob/master/docs/synchronization.md) +# +# Next, configure the config map with rebalanced strategy: +# +# ``` +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: my-config +# data: +# test-scale: "4" +# test-scale-strategy: "rebalanced" +# ``` +# +# By setting `test-scale: "rebalanced"`, we're essentially telling the semaphore to continuously rebalance +# the number of locks that can be distributed to each unique "rebalanceKey" +# +# +# Next, kick off this example twice: +# - `argo submit examples/rebalance-key.yaml -p 'num=100' -p 'rebalanceKey=A'` +# - `argo submit examples/rebalance-key.yaml -p 'num=100' -p 'rebalanceKey=B'` +# +# The initial node is responsible for creating "num" child nodes, so wait just a few seconds. You should see +# that there are two workflows that each have access to 2 locks (in this case, `45js9` and `8h7g2`). +# +# rebalance-key-demo-45js9-acquire-lock-2305596013 2/2 Running 0 15s +# rebalance-key-demo-45js9-acquire-lock-1265891257 2/2 Running 0 15s +# rebalance-key-demo-8h7g2-acquire-lock-1096570232 2/2 Running 0 6s +# rebalance-key-demo-8h7g2-acquire-lock-3005783468 2/2 Running 0 7s +# +# Experiment with different settings to see how this workflow strategy behaves in different scenarios. +# +# If we do not wish to "rebalance", and use the default semaphore behavior instead, we can either specify +# "default" or simply not include the lock name in "semaphoreStrategy". +# +# Note that when "rebalanced" is used, all lock requesters with no rebalanceKey specified will all be +# grouped together. Also note that priorities are currently ignored with semaphores using the rebalance +# strategy. Also note that rebalance key works anywhere a semaphore can be used (e.g. workflow level or +# virtual node (steps,dag) level) +#--- +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: rebalance-key-demo- +spec: + activeDeadlineSeconds: 100000 + entrypoint: synchronization-tmpl-level-example + serviceAccountName: argo + arguments: + parameters: + - name: num + value: 1 + - name: rebalanceKey + value: "unset" + podGC: + strategy: OnPodSuccess + templates: + - name: synchronization-tmpl-level-example + steps: + - - name: generate + template: gen-number-list + - - name: synchronization-acquire-lock + template: acquire-lock + withParam: "{{steps.generate.outputs.result}}" + + - name: gen-number-list + script: + image: python:alpine3.6 + command: [python] + source: | + import json + import sys + json.dump([i for i in range(0, {{workflow.parameters.num}})], sys.stdout) + - name: acquire-lock + synchronization: + semaphore: + configMapKeyRef: + name: scale-config + key: test-scale + rebalanceKey: "{{workflow.parameters.rebalanceKey}}" + container: + image: alpine:latest + command: [sh, -c] + args: ["echo acquired lock; sleep $((20 + RANDOM % 11));"] diff --git a/manifests/base/crds/full/argoproj.io_clusterworkflowtemplates.yaml b/manifests/base/crds/full/argoproj.io_clusterworkflowtemplates.yaml index 304819ab9df8..dbdcddbe5181 100644 --- a/manifests/base/crds/full/argoproj.io_clusterworkflowtemplates.yaml +++ b/manifests/base/crds/full/argoproj.io_clusterworkflowtemplates.yaml @@ -1852,6 +1852,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object templateDefaults: @@ -9241,6 +9243,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -17330,6 +17334,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: diff --git a/manifests/base/crds/full/argoproj.io_cronworkflows.yaml b/manifests/base/crds/full/argoproj.io_cronworkflows.yaml index db6d4c5c741d..79a8b8c3dac5 100644 --- a/manifests/base/crds/full/argoproj.io_cronworkflows.yaml +++ b/manifests/base/crds/full/argoproj.io_cronworkflows.yaml @@ -1873,6 +1873,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object templateDefaults: @@ -9262,6 +9264,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -17351,6 +17355,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: diff --git a/manifests/base/crds/full/argoproj.io_workflows.yaml b/manifests/base/crds/full/argoproj.io_workflows.yaml index cecd175d765d..6dddbf635cec 100644 --- a/manifests/base/crds/full/argoproj.io_workflows.yaml +++ b/manifests/base/crds/full/argoproj.io_workflows.yaml @@ -1866,6 +1866,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object templateDefaults: @@ -9255,6 +9257,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -17344,6 +17348,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -29020,6 +29026,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -31549,6 +31557,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object templateDefaults: @@ -38938,6 +38948,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -47027,6 +47039,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: diff --git a/manifests/base/crds/full/argoproj.io_workflowtasksets.yaml b/manifests/base/crds/full/argoproj.io_workflowtasksets.yaml index 5dd6cc8c85d4..fd65e0c33e68 100644 --- a/manifests/base/crds/full/argoproj.io_workflowtasksets.yaml +++ b/manifests/base/crds/full/argoproj.io_workflowtasksets.yaml @@ -7414,6 +7414,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: diff --git a/manifests/base/crds/full/argoproj.io_workflowtemplates.yaml b/manifests/base/crds/full/argoproj.io_workflowtemplates.yaml index 0f794456fdca..2c4010dddfb0 100644 --- a/manifests/base/crds/full/argoproj.io_workflowtemplates.yaml +++ b/manifests/base/crds/full/argoproj.io_workflowtemplates.yaml @@ -1851,6 +1851,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object templateDefaults: @@ -9240,6 +9242,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: @@ -17329,6 +17333,8 @@ spec: required: - key type: object + rebalanceKey: + type: string type: object type: object timeout: diff --git a/pkg/apis/workflow/v1alpha1/generated.pb.go b/pkg/apis/workflow/v1alpha1/generated.pb.go index 57b68ccd7ce8..0463328a26fc 100644 --- a/pkg/apis/workflow/v1alpha1/generated.pb.go +++ b/pkg/apis/workflow/v1alpha1/generated.pb.go @@ -4360,671 +4360,673 @@ func init() { } var fileDescriptor_724696e352c3df5f = []byte{ - // 10621 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x7d, 0x6b, 0x70, 0x24, 0xc7, - 0x79, 0x18, 0x67, 0x81, 0xc5, 0xe3, 0xc3, 0xf3, 0xfa, 0x5e, 0x4b, 0x90, 0x3c, 0xd0, 0x43, 0x91, - 0x21, 0x6d, 0x0a, 0x67, 0xde, 0x49, 0x09, 0x23, 0x25, 0x92, 0xf0, 0x38, 0xe0, 0x40, 0x00, 0x07, - 0xb0, 0x17, 0x77, 0x67, 0x52, 0x8c, 0xa4, 0xc1, 0x6e, 0x63, 0x77, 0x88, 0xdd, 0x99, 0xd5, 0xcc, - 0x2c, 0x70, 0x20, 0x8f, 0x92, 0x22, 0xeb, 0x19, 0x2b, 0x56, 0x62, 0x4b, 0xb2, 0xa4, 0x24, 0x55, - 0x8a, 0x22, 0x25, 0x2a, 0xc5, 0x95, 0x94, 0x5c, 0xf9, 0x91, 0xb2, 0xff, 0xa5, 0x52, 0x2e, 0xa5, - 0x9c, 0xaa, 0xc8, 0x65, 0x26, 0xd2, 0x8f, 0x18, 0x8c, 0x90, 0x44, 0x55, 0x49, 0x4a, 0x55, 0x89, - 0x2a, 0x76, 0xec, 0xcb, 0xa3, 0x52, 0xfd, 0x9c, 0xee, 0xd9, 0x59, 0x1c, 0x70, 0xd7, 0xc0, 0xb1, - 0xec, 0x5f, 0xc0, 0x7e, 0xfd, 0xf5, 0xf7, 0x75, 0xf7, 0xf4, 0x7c, 0xfd, 0xbd, 0xfa, 0x1b, 0x58, - 0xab, 0xf9, 0x49, 0xbd, 0xbd, 0x31, 0x55, 0x09, 0x9b, 0x17, 0xbd, 0xa8, 0x16, 0xb6, 0xa2, 0xf0, - 0x55, 0xf6, 0xcf, 0x3b, 0x77, 0xc2, 0x68, 0x6b, 0xb3, 0x11, 0xee, 0xc4, 0x17, 0xb7, 0x2f, 0x5f, - 0x6c, 0x6d, 0xd5, 0x2e, 0x7a, 0x2d, 0x3f, 0xbe, 0x28, 0xa1, 0x17, 0xb7, 0x9f, 0xf3, 0x1a, 0xad, - 0xba, 0xf7, 0xdc, 0xc5, 0x1a, 0x09, 0x48, 0xe4, 0x25, 0xa4, 0x3a, 0xd5, 0x8a, 0xc2, 0x24, 0x44, - 0x1f, 0x48, 0x29, 0x4e, 0x49, 0x8a, 0xec, 0x9f, 0x0f, 0x2b, 0x8a, 0x53, 0xdb, 0x97, 0xa7, 0x5a, - 0x5b, 0xb5, 0x29, 0x4a, 0x71, 0x4a, 0x42, 0xa7, 0x24, 0xc5, 0x89, 0x77, 0x6a, 0x63, 0xaa, 0x85, - 0xb5, 0xf0, 0x22, 0x23, 0xbc, 0xd1, 0xde, 0x64, 0xbf, 0xd8, 0x0f, 0xf6, 0x1f, 0x67, 0x38, 0xe1, - 0x6e, 0x3d, 0x1f, 0x4f, 0xf9, 0x21, 0x1d, 0xdf, 0xc5, 0x4a, 0x18, 0x91, 0x8b, 0xdb, 0x1d, 0x83, - 0x9a, 0x78, 0x87, 0x86, 0xd3, 0x0a, 0x1b, 0x7e, 0x65, 0x37, 0x0f, 0xeb, 0x5d, 0x29, 0x56, 0xd3, - 0xab, 0xd4, 0xfd, 0x80, 0x44, 0xbb, 0xe9, 0xd4, 0x9b, 0x24, 0xf1, 0xf2, 0x7a, 0x5d, 0xec, 0xd6, - 0x2b, 0x6a, 0x07, 0x89, 0xdf, 0x24, 0x1d, 0x1d, 0xfe, 0xe2, 0xdd, 0x3a, 0xc4, 0x95, 0x3a, 0x69, - 0x7a, 0x1d, 0xfd, 0x2e, 0x77, 0xeb, 0xd7, 0x4e, 0xfc, 0xc6, 0x45, 0x3f, 0x48, 0xe2, 0x24, 0xca, - 0x76, 0x72, 0xaf, 0x40, 0xdf, 0x74, 0x33, 0x6c, 0x07, 0x09, 0x7a, 0x2f, 0x14, 0xb7, 0xbd, 0x46, - 0x9b, 0x94, 0x9c, 0xc7, 0x9d, 0xa7, 0x07, 0x67, 0x9e, 0xfc, 0xfe, 0xde, 0xe4, 0x43, 0xfb, 0x7b, - 0x93, 0xc5, 0x1b, 0x14, 0x78, 0x67, 0x6f, 0xf2, 0x0c, 0x09, 0x2a, 0x61, 0xd5, 0x0f, 0x6a, 0x17, - 0x5f, 0x8d, 0xc3, 0x60, 0xea, 0x5a, 0xbb, 0xb9, 0x41, 0x22, 0xcc, 0xfb, 0xb8, 0x7f, 0x50, 0x80, - 0xb1, 0xe9, 0xa8, 0x52, 0xf7, 0xb7, 0x49, 0x39, 0xa1, 0xf4, 0x6b, 0xbb, 0xa8, 0x0e, 0x3d, 0x89, - 0x17, 0x31, 0x72, 0x43, 0x97, 0x56, 0xa6, 0xee, 0xf7, 0xb9, 0x4f, 0xad, 0x7b, 0x91, 0xa4, 0x3d, - 0xd3, 0xbf, 0xbf, 0x37, 0xd9, 0xb3, 0xee, 0x45, 0x98, 0xb2, 0x40, 0x0d, 0xe8, 0x0d, 0xc2, 0x80, - 0x94, 0x0a, 0x8c, 0xd5, 0xb5, 0xfb, 0x67, 0x75, 0x2d, 0x0c, 0xd4, 0x3c, 0x66, 0x06, 0xf6, 0xf7, - 0x26, 0x7b, 0x29, 0x04, 0x33, 0x2e, 0x74, 0x5e, 0xaf, 0xf9, 0xad, 0x52, 0x8f, 0xad, 0x79, 0xbd, - 0xec, 0xb7, 0xcc, 0x79, 0xbd, 0xec, 0xb7, 0x30, 0x65, 0xe1, 0x7e, 0xbe, 0x00, 0x83, 0xd3, 0x51, - 0xad, 0xdd, 0x24, 0x41, 0x12, 0xa3, 0x8f, 0x03, 0xb4, 0xbc, 0xc8, 0x6b, 0x92, 0x84, 0x44, 0x71, - 0xc9, 0x79, 0xbc, 0xe7, 0xe9, 0xa1, 0x4b, 0x4b, 0xf7, 0xcf, 0x7e, 0x4d, 0xd2, 0x9c, 0x41, 0xe2, - 0x91, 0x83, 0x02, 0xc5, 0x58, 0x63, 0x89, 0x5e, 0x87, 0x41, 0x2f, 0x4a, 0xfc, 0x4d, 0xaf, 0x92, - 0xc4, 0xa5, 0x02, 0xe3, 0xff, 0xc2, 0xfd, 0xf3, 0x9f, 0x16, 0x24, 0x67, 0x4e, 0x09, 0xf6, 0x83, - 0x12, 0x12, 0xe3, 0x94, 0x9f, 0xfb, 0xdb, 0xbd, 0x30, 0x34, 0x1d, 0x25, 0x0b, 0xb3, 0xe5, 0xc4, - 0x4b, 0xda, 0x31, 0xfa, 0x3d, 0x07, 0x4e, 0xc7, 0x7c, 0xd9, 0x7c, 0x12, 0xaf, 0x45, 0x61, 0x85, - 0xc4, 0x31, 0xa9, 0x8a, 0x75, 0xd9, 0xb4, 0x32, 0x2e, 0xc9, 0x6c, 0xaa, 0xdc, 0xc9, 0xe8, 0x4a, - 0x90, 0x44, 0xbb, 0x33, 0xcf, 0x89, 0x31, 0x9f, 0xce, 0xc1, 0xf8, 0xe4, 0x5b, 0x93, 0x48, 0x4e, - 0x85, 0x52, 0xe2, 0x8f, 0x18, 0xe7, 0x8d, 0x1a, 0x7d, 0xcd, 0x81, 0xe1, 0x56, 0x58, 0x8d, 0x31, - 0xa9, 0x84, 0xed, 0x16, 0xa9, 0x8a, 0xe5, 0xfd, 0xb0, 0xdd, 0x69, 0xac, 0x69, 0x1c, 0xf8, 0xf8, - 0xcf, 0x88, 0xf1, 0x0f, 0xeb, 0x4d, 0xd8, 0x18, 0x0a, 0x7a, 0x1e, 0x86, 0x83, 0x30, 0x29, 0xb7, - 0x48, 0xc5, 0xdf, 0xf4, 0x49, 0x95, 0x6d, 0xfc, 0x81, 0xb4, 0xe7, 0x35, 0xad, 0x0d, 0x1b, 0x98, - 0x13, 0xf3, 0x50, 0xea, 0xb6, 0x72, 0x68, 0x1c, 0x7a, 0xb6, 0xc8, 0x2e, 0x17, 0x36, 0x98, 0xfe, - 0x8b, 0xce, 0x48, 0x01, 0x44, 0x5f, 0xe3, 0x01, 0x21, 0x59, 0xde, 0x53, 0x78, 0xde, 0x99, 0x78, - 0x3f, 0x9c, 0xea, 0x18, 0xfa, 0x51, 0x08, 0xb8, 0x3f, 0xe8, 0x83, 0x01, 0xf9, 0x28, 0xd0, 0xe3, - 0xd0, 0x1b, 0x78, 0x4d, 0x29, 0xe7, 0x86, 0xc5, 0x3c, 0x7a, 0xaf, 0x79, 0x4d, 0xfa, 0x86, 0x7b, - 0x4d, 0x42, 0x31, 0x5a, 0x5e, 0x52, 0x67, 0x74, 0x34, 0x8c, 0x35, 0x2f, 0xa9, 0x63, 0xd6, 0x82, - 0x1e, 0x85, 0xde, 0x66, 0x58, 0x25, 0x6c, 0x2d, 0x8a, 0x5c, 0x42, 0xac, 0x84, 0x55, 0x82, 0x19, - 0x94, 0xf6, 0xdf, 0x8c, 0xc2, 0x66, 0xa9, 0xd7, 0xec, 0x3f, 0x1f, 0x85, 0x4d, 0xcc, 0x5a, 0xd0, - 0x57, 0x1d, 0x18, 0x97, 0x7b, 0x7b, 0x39, 0xac, 0x78, 0x89, 0x1f, 0x06, 0xa5, 0x22, 0x93, 0x28, - 0xd8, 0xde, 0x2b, 0x25, 0x29, 0xcf, 0x94, 0xc4, 0x10, 0xc6, 0xb3, 0x2d, 0xb8, 0x63, 0x14, 0xe8, - 0x12, 0x40, 0xad, 0x11, 0x6e, 0x78, 0x0d, 0xba, 0x20, 0xa5, 0x3e, 0x36, 0x05, 0x25, 0x19, 0x16, - 0x54, 0x0b, 0xd6, 0xb0, 0xd0, 0x2d, 0xe8, 0xf7, 0xb8, 0xf4, 0x2f, 0xf5, 0xb3, 0x49, 0xbc, 0x68, - 0x63, 0x12, 0xc6, 0x71, 0x32, 0x33, 0xb4, 0xbf, 0x37, 0xd9, 0x2f, 0x80, 0x58, 0xb2, 0x43, 0xcf, - 0xc2, 0x40, 0xd8, 0xa2, 0xe3, 0xf6, 0x1a, 0xa5, 0x01, 0xb6, 0x31, 0xc7, 0xc5, 0x58, 0x07, 0x56, - 0x05, 0x1c, 0x2b, 0x0c, 0xf4, 0x0c, 0xf4, 0xc7, 0xed, 0x0d, 0xfa, 0x1c, 0x4b, 0x83, 0x6c, 0x62, - 0x63, 0x02, 0xb9, 0xbf, 0xcc, 0xc1, 0x58, 0xb6, 0xa3, 0x77, 0xc3, 0x50, 0x44, 0x2a, 0xed, 0x28, - 0x26, 0xf4, 0xc1, 0x96, 0x80, 0xd1, 0x3e, 0x2d, 0xd0, 0x87, 0x70, 0xda, 0x84, 0x75, 0x3c, 0xf4, - 0x3e, 0x18, 0xa5, 0x0f, 0xf8, 0xca, 0xad, 0x56, 0x44, 0xe2, 0x98, 0x3e, 0xd5, 0x21, 0xc6, 0xe8, - 0x9c, 0xe8, 0x39, 0x3a, 0x6f, 0xb4, 0xe2, 0x0c, 0x36, 0xba, 0x0d, 0xe0, 0x29, 0x99, 0x51, 0x1a, - 0x66, 0x8b, 0xb9, 0x6c, 0x6f, 0x47, 0x2c, 0xcc, 0xce, 0x8c, 0xd2, 0xe7, 0x98, 0xfe, 0xc6, 0x1a, - 0x3f, 0xba, 0x3e, 0x55, 0xd2, 0x20, 0x09, 0xa9, 0x96, 0x46, 0xd8, 0x84, 0xd5, 0xfa, 0xcc, 0x71, - 0x30, 0x96, 0xed, 0xee, 0xdf, 0x29, 0x80, 0x46, 0x05, 0xcd, 0xc0, 0x80, 0x90, 0x6b, 0xe2, 0x95, - 0x9c, 0x79, 0x4a, 0x3e, 0x07, 0xf9, 0x04, 0xef, 0xec, 0xe5, 0xca, 0x43, 0xd5, 0x0f, 0xbd, 0x01, - 0x43, 0xad, 0xb0, 0xba, 0x42, 0x12, 0xaf, 0xea, 0x25, 0x9e, 0x38, 0xcd, 0x2d, 0x9c, 0x30, 0x92, - 0xe2, 0xcc, 0x18, 0x7d, 0x74, 0x6b, 0x29, 0x0b, 0xac, 0xf3, 0x43, 0x2f, 0x00, 0x8a, 0x49, 0xb4, - 0xed, 0x57, 0xc8, 0x74, 0xa5, 0x42, 0x55, 0x22, 0xf6, 0x02, 0xf4, 0xb0, 0xc9, 0x4c, 0x88, 0xc9, - 0xa0, 0x72, 0x07, 0x06, 0xce, 0xe9, 0xe5, 0xbe, 0x59, 0x80, 0x51, 0x6d, 0xae, 0x2d, 0x52, 0x41, - 0xdf, 0x71, 0x60, 0x4c, 0x1d, 0x67, 0x33, 0xbb, 0xd7, 0xe8, 0xae, 0xe2, 0x87, 0x15, 0xb1, 0xf9, - 0x7c, 0x29, 0x2f, 0xf5, 0x53, 0xf0, 0xe1, 0xb2, 0xfe, 0xbc, 0x98, 0xc3, 0x58, 0xa6, 0x15, 0x67, - 0x87, 0x35, 0xf1, 0x15, 0x07, 0xce, 0xe4, 0x91, 0xc8, 0x91, 0xb9, 0x75, 0x5d, 0xe6, 0x5a, 0x15, - 0x5e, 0x94, 0x2b, 0x9d, 0x8c, 0x2e, 0xc7, 0xff, 0x5f, 0x01, 0xc6, 0xf5, 0x2d, 0xc4, 0x34, 0x81, - 0x7f, 0xe1, 0xc0, 0x59, 0x39, 0x03, 0x4c, 0xe2, 0x76, 0x23, 0xb3, 0xbc, 0x4d, 0xab, 0xcb, 0xcb, - 0x4f, 0xd2, 0xe9, 0x3c, 0x7e, 0x7c, 0x99, 0x1f, 0x13, 0xcb, 0x7c, 0x36, 0x17, 0x07, 0xe7, 0x0f, - 0x75, 0xe2, 0x5b, 0x0e, 0x4c, 0x74, 0x27, 0x9a, 0xb3, 0xf0, 0x2d, 0x73, 0xe1, 0x5f, 0xb6, 0x37, - 0x49, 0xce, 0x9e, 0x2d, 0x3f, 0x9b, 0xac, 0xfe, 0x00, 0x7e, 0x73, 0x00, 0x3a, 0xce, 0x10, 0xf4, - 0x1c, 0x0c, 0x09, 0x71, 0xbc, 0x1c, 0xd6, 0x62, 0x36, 0xc8, 0x01, 0xfe, 0xae, 0x4d, 0xa7, 0x60, - 0xac, 0xe3, 0xa0, 0x2a, 0x14, 0xe2, 0xcb, 0x62, 0xe8, 0x16, 0xc4, 0x5b, 0xf9, 0xb2, 0xd2, 0x22, - 0xfb, 0xf6, 0xf7, 0x26, 0x0b, 0xe5, 0xcb, 0xb8, 0x10, 0x5f, 0xa6, 0x9a, 0x7a, 0xcd, 0x4f, 0xec, - 0x69, 0xea, 0x0b, 0x7e, 0xa2, 0xf8, 0x30, 0x4d, 0x7d, 0xc1, 0x4f, 0x30, 0x65, 0x41, 0x2d, 0x90, - 0x7a, 0x92, 0xb4, 0xd8, 0x89, 0x6f, 0xc5, 0x02, 0xb9, 0xba, 0xbe, 0xbe, 0xa6, 0x78, 0x31, 0xfd, - 0x82, 0x42, 0x30, 0xe3, 0x82, 0x3e, 0xe7, 0xd0, 0x15, 0xe7, 0x8d, 0x61, 0xb4, 0x2b, 0x14, 0x87, - 0xeb, 0xf6, 0xb6, 0x40, 0x18, 0xed, 0x2a, 0xe6, 0xe2, 0x41, 0xaa, 0x06, 0xac, 0xb3, 0x66, 0x13, - 0xaf, 0x6e, 0xc6, 0x4c, 0x4f, 0xb0, 0x33, 0xf1, 0xb9, 0xf9, 0x72, 0x66, 0xe2, 0x73, 0xf3, 0x65, - 0xcc, 0xb8, 0xd0, 0x07, 0x1a, 0x79, 0x3b, 0x42, 0xc7, 0xb0, 0xf0, 0x40, 0xb1, 0xb7, 0x63, 0x3e, - 0x50, 0xec, 0xed, 0x60, 0xca, 0x82, 0x72, 0x0a, 0xe3, 0x98, 0xa9, 0x14, 0x56, 0x38, 0xad, 0x96, - 0xcb, 0x26, 0xa7, 0xd5, 0x72, 0x19, 0x53, 0x16, 0x6c, 0x93, 0x56, 0x62, 0xa6, 0x8f, 0xd8, 0xd9, - 0xa4, 0xb3, 0x19, 0x4e, 0x0b, 0xb3, 0x65, 0x4c, 0x59, 0x50, 0x91, 0xe1, 0xbd, 0xd6, 0x8e, 0xb8, - 0x32, 0x33, 0x74, 0x69, 0xd5, 0xc2, 0x7e, 0xa1, 0xe4, 0x14, 0xb7, 0xc1, 0xfd, 0xbd, 0xc9, 0x22, - 0x03, 0x61, 0xce, 0xc8, 0xfd, 0xdd, 0x9e, 0x54, 0x5c, 0x48, 0x79, 0x8e, 0xfe, 0x36, 0x3b, 0x08, - 0x85, 0x2c, 0x10, 0xaa, 0xaf, 0x73, 0x6c, 0xaa, 0xef, 0x69, 0x7e, 0xe2, 0x19, 0xec, 0x70, 0x96, - 0x3f, 0xfa, 0x35, 0xa7, 0xd3, 0xb6, 0xf5, 0xec, 0x9f, 0x65, 0xe9, 0xc1, 0xcc, 0xcf, 0x8a, 0x03, - 0x4d, 0xde, 0x89, 0xcf, 0x39, 0xa9, 0x12, 0x11, 0x77, 0x3b, 0x07, 0x3e, 0x62, 0x9e, 0x03, 0x16, - 0x0d, 0x72, 0x5d, 0xee, 0x7f, 0xde, 0x81, 0x11, 0x09, 0xa7, 0xea, 0x71, 0x8c, 0x6e, 0xc1, 0x80, - 0x1c, 0xa9, 0x78, 0x7a, 0x36, 0x7d, 0x01, 0x4a, 0x89, 0x57, 0x83, 0x51, 0xdc, 0xdc, 0xef, 0xf4, - 0x01, 0x4a, 0xcf, 0xaa, 0x56, 0x18, 0xfb, 0x4c, 0x12, 0xdd, 0xc3, 0x29, 0x14, 0x68, 0xa7, 0xd0, - 0x0d, 0x9b, 0xa7, 0x50, 0x3a, 0x2c, 0xe3, 0x3c, 0xfa, 0xb5, 0x8c, 0xdc, 0xe6, 0x07, 0xd3, 0x87, - 0x8f, 0x45, 0x6e, 0x6b, 0x43, 0x38, 0x58, 0x82, 0x6f, 0x0b, 0x09, 0xce, 0x8f, 0xae, 0x5f, 0xb2, - 0x2b, 0xc1, 0xb5, 0x51, 0x64, 0x65, 0x79, 0xc4, 0x25, 0x2c, 0x3f, 0xbb, 0x6e, 0x5a, 0x95, 0xb0, - 0x1a, 0x57, 0x53, 0xd6, 0x46, 0x5c, 0xd6, 0xf6, 0xd9, 0xe2, 0xa9, 0xc9, 0xda, 0x2c, 0x4f, 0x25, - 0x75, 0x5f, 0x93, 0x52, 0x97, 0x9f, 0x5a, 0x2f, 0x59, 0x96, 0xba, 0x1a, 0xdf, 0x4e, 0xf9, 0xfb, - 0x51, 0x38, 0xdb, 0x89, 0x87, 0xc9, 0x26, 0xba, 0x08, 0x83, 0x95, 0x30, 0xd8, 0xf4, 0x6b, 0x2b, - 0x5e, 0x4b, 0xd8, 0x6b, 0x4a, 0x16, 0xcd, 0xca, 0x06, 0x9c, 0xe2, 0xa0, 0xc7, 0xb8, 0xe0, 0xe1, - 0x1e, 0x91, 0x21, 0x81, 0xda, 0xb3, 0x44, 0x76, 0x99, 0x14, 0x7a, 0xcf, 0xc0, 0x57, 0xbf, 0x31, - 0xf9, 0xd0, 0x27, 0xfe, 0xfd, 0xe3, 0x0f, 0xb9, 0xbf, 0xdf, 0x03, 0x8f, 0xe4, 0xf2, 0x14, 0xda, - 0xfa, 0x6f, 0x1a, 0xda, 0xba, 0xd6, 0x2e, 0xa4, 0xc8, 0x4d, 0x9b, 0x8a, 0xac, 0x46, 0x3e, 0x4f, - 0x2f, 0xd7, 0x9a, 0x71, 0xfe, 0xa0, 0xe8, 0x42, 0x05, 0x5e, 0x93, 0xc4, 0x2d, 0xaf, 0x42, 0xc4, - 0xec, 0xd5, 0x42, 0x5d, 0x93, 0x0d, 0x38, 0xc5, 0xe1, 0x26, 0xf4, 0xa6, 0xd7, 0x6e, 0x24, 0xc2, - 0x51, 0xa6, 0x99, 0xd0, 0x0c, 0x8c, 0x65, 0x3b, 0xfa, 0xbb, 0x0e, 0xa0, 0x4e, 0xae, 0xe2, 0x45, - 0x5c, 0x3f, 0x8e, 0x75, 0x98, 0x39, 0xb7, 0xaf, 0x19, 0xe1, 0xda, 0x4c, 0x73, 0xc6, 0xa1, 0x3d, - 0xd3, 0x8f, 0xa5, 0xe7, 0x10, 0x37, 0x0e, 0x0e, 0xe1, 0x43, 0x63, 0xae, 0x96, 0x4a, 0x85, 0xc4, - 0x31, 0x77, 0xc7, 0xe9, 0xae, 0x16, 0x06, 0xc6, 0xb2, 0x1d, 0x4d, 0x42, 0x91, 0x44, 0x51, 0x18, - 0x09, 0x5b, 0x9b, 0x6d, 0xe3, 0x2b, 0x14, 0x80, 0x39, 0xdc, 0xfd, 0x49, 0x01, 0x4a, 0xdd, 0xac, - 0x13, 0xf4, 0x5b, 0x9a, 0x5d, 0x2d, 0x2c, 0x27, 0x61, 0xf8, 0x85, 0xc7, 0x67, 0x13, 0x65, 0x0d, - 0xc0, 0x2e, 0x16, 0xb6, 0x68, 0xc5, 0xd9, 0x01, 0x4e, 0x7c, 0x49, 0xb3, 0xb0, 0x75, 0x12, 0x39, - 0x07, 0xfc, 0xa6, 0x79, 0xc0, 0xaf, 0xd9, 0x9e, 0x94, 0x7e, 0xcc, 0xff, 0x61, 0x11, 0x4e, 0xcb, - 0xd6, 0x32, 0xa1, 0x47, 0xe5, 0x8b, 0x6d, 0x12, 0xed, 0xa2, 0x1f, 0x3a, 0x70, 0xc6, 0xcb, 0xba, - 0x6e, 0x7c, 0x72, 0x0c, 0x0b, 0xad, 0x71, 0x9d, 0x9a, 0xce, 0xe1, 0xc8, 0x17, 0xfa, 0x92, 0x58, - 0xe8, 0x33, 0x79, 0x28, 0x5d, 0xfc, 0xee, 0xb9, 0x13, 0x40, 0xcf, 0xc3, 0xb0, 0x84, 0x33, 0x77, - 0x0f, 0x7f, 0xc5, 0x95, 0x73, 0x7b, 0x5a, 0x6b, 0xc3, 0x06, 0x26, 0xed, 0x99, 0x90, 0x66, 0xab, - 0xe1, 0x25, 0x44, 0x73, 0x14, 0xa9, 0x9e, 0xeb, 0x5a, 0x1b, 0x36, 0x30, 0xd1, 0x53, 0xd0, 0x17, - 0x84, 0x55, 0xb2, 0x58, 0x15, 0x0e, 0xe2, 0x51, 0xd1, 0xa7, 0xef, 0x1a, 0x83, 0x62, 0xd1, 0x8a, - 0x9e, 0x4c, 0xbd, 0x71, 0x45, 0xf6, 0x0a, 0x0d, 0xe5, 0x79, 0xe2, 0xd0, 0xdf, 0x77, 0x60, 0x90, - 0xf6, 0x58, 0xdf, 0x6d, 0x11, 0x7a, 0xb6, 0xd1, 0x27, 0x52, 0x3d, 0x9e, 0x27, 0x72, 0x4d, 0xb2, - 0x31, 0x5d, 0x1d, 0x83, 0x0a, 0xfe, 0xc9, 0xb7, 0x26, 0x07, 0xe4, 0x0f, 0x9c, 0x8e, 0x6a, 0x62, - 0x01, 0x1e, 0xee, 0xfa, 0x34, 0x8f, 0x14, 0x0a, 0xf8, 0x2b, 0x30, 0x6a, 0x0e, 0xe2, 0x48, 0x71, - 0x80, 0x7f, 0xae, 0xbd, 0x76, 0x7c, 0x5e, 0x42, 0x9e, 0x3d, 0x30, 0x6d, 0x56, 0x6d, 0x86, 0x39, - 0xb1, 0xf5, 0xcc, 0xcd, 0x30, 0x27, 0x36, 0xc3, 0x9c, 0xfb, 0x7b, 0x4e, 0xfa, 0x6a, 0x6a, 0x6a, - 0x1e, 0x3d, 0x98, 0xdb, 0x51, 0x43, 0x08, 0x62, 0x75, 0x30, 0x5f, 0xc7, 0xcb, 0x98, 0xc2, 0xd1, - 0x97, 0x34, 0xe9, 0x48, 0xbb, 0xb5, 0x45, 0x58, 0xc3, 0x92, 0x8b, 0xde, 0x20, 0xdc, 0x29, 0xff, - 0x44, 0x03, 0xce, 0x0e, 0xc1, 0xfd, 0xb1, 0x03, 0x8f, 0x1d, 0xa8, 0xb4, 0xe6, 0x0e, 0xdc, 0x79, - 0xe0, 0x03, 0xa7, 0xc7, 0x5a, 0x44, 0x5a, 0xe1, 0x75, 0xbc, 0x2c, 0x9e, 0x97, 0x3a, 0xd6, 0x30, - 0x07, 0x63, 0xd9, 0xee, 0xfe, 0xd0, 0x81, 0x2c, 0x3d, 0xe4, 0xc1, 0x68, 0x3b, 0x26, 0x11, 0x3d, - 0x21, 0xcb, 0xa4, 0x12, 0x11, 0xb9, 0xdb, 0x9e, 0x9c, 0xe2, 0xc1, 0x7b, 0x3a, 0xe0, 0xa9, 0x4a, - 0x18, 0x91, 0xa9, 0xed, 0xe7, 0xa6, 0x38, 0xc6, 0x12, 0xd9, 0x2d, 0x93, 0x06, 0xa1, 0x34, 0x66, - 0xd0, 0xfe, 0xde, 0xe4, 0xe8, 0x75, 0x83, 0x00, 0xce, 0x10, 0xa4, 0x2c, 0x5a, 0x5e, 0x1c, 0xef, - 0x84, 0x51, 0x55, 0xb0, 0x28, 0x1c, 0x99, 0xc5, 0x9a, 0x41, 0x00, 0x67, 0x08, 0xba, 0x6f, 0x52, - 0x6b, 0x50, 0x57, 0x42, 0xd1, 0x37, 0xa8, 0x2a, 0x43, 0x21, 0x33, 0x8d, 0x70, 0x63, 0x36, 0x0c, - 0x12, 0xcf, 0x0f, 0x88, 0x8c, 0xfd, 0xaf, 0x5b, 0x52, 0x79, 0x0d, 0xda, 0xa9, 0x4b, 0xbe, 0xb3, - 0x0d, 0xe7, 0x8c, 0x85, 0xaa, 0x2c, 0x1b, 0x8d, 0x70, 0x23, 0x1b, 0xd4, 0xa3, 0x48, 0x98, 0xb5, - 0xb8, 0x3f, 0x73, 0xe0, 0x7c, 0x17, 0xdd, 0x1a, 0x7d, 0xc5, 0x81, 0x91, 0x8d, 0xb7, 0xc5, 0xdc, - 0xcc, 0x61, 0xa0, 0xf7, 0xc1, 0x28, 0x05, 0xd0, 0x83, 0x65, 0x3e, 0x8c, 0x9a, 0x5e, 0x22, 0x26, - 0xa8, 0x02, 0x4e, 0x33, 0x46, 0x2b, 0xce, 0x60, 0xbb, 0xbf, 0x5e, 0x80, 0x1c, 0x2e, 0xe8, 0x59, - 0x18, 0x20, 0x41, 0xb5, 0x15, 0xfa, 0x41, 0x22, 0x64, 0x8b, 0x12, 0x62, 0x57, 0x04, 0x1c, 0x2b, - 0x0c, 0x61, 0x4e, 0x88, 0x85, 0x29, 0x74, 0x98, 0x13, 0x62, 0xe4, 0x29, 0x0e, 0xaa, 0xc1, 0xb8, - 0xc7, 0xc3, 0x25, 0x6c, 0xef, 0xb1, 0x6d, 0xda, 0x73, 0x94, 0x6d, 0x7a, 0x86, 0x45, 0x33, 0x33, - 0x24, 0x70, 0x07, 0x51, 0xf4, 0x6e, 0x18, 0x6a, 0xc7, 0xa4, 0x3c, 0xb7, 0x34, 0x1b, 0x91, 0x2a, - 0x37, 0x72, 0xb5, 0x30, 0xde, 0xf5, 0xb4, 0x09, 0xeb, 0x78, 0xee, 0xbf, 0x74, 0xa0, 0x7f, 0xc6, - 0xab, 0x6c, 0x85, 0x9b, 0x9b, 0x74, 0x29, 0xaa, 0xed, 0x28, 0xf5, 0x53, 0x69, 0x4b, 0x31, 0x27, - 0xe0, 0x58, 0x61, 0xa0, 0x75, 0xe8, 0xe3, 0x2f, 0xbc, 0x78, 0xed, 0x7e, 0x51, 0x9b, 0x8f, 0x4a, - 0xcb, 0x61, 0xdb, 0xa1, 0x9d, 0xf8, 0x8d, 0x29, 0x9e, 0x96, 0x33, 0xb5, 0x18, 0x24, 0xab, 0x51, - 0x39, 0x89, 0xfc, 0xa0, 0x36, 0x03, 0x54, 0xfa, 0xcf, 0x33, 0x1a, 0x58, 0xd0, 0xa2, 0xd3, 0x68, - 0x7a, 0xb7, 0x24, 0x3b, 0xa1, 0x6b, 0xa8, 0x69, 0xac, 0xa4, 0x4d, 0x58, 0xc7, 0x73, 0x7f, 0xdf, - 0x81, 0xc1, 0x19, 0x2f, 0xf6, 0x2b, 0x7f, 0x86, 0x84, 0xcf, 0x87, 0xa0, 0x38, 0xeb, 0x55, 0xea, - 0x04, 0x5d, 0xcf, 0xda, 0xb0, 0x43, 0x97, 0x9e, 0xce, 0x63, 0xa3, 0xec, 0x59, 0x9d, 0xd3, 0x48, - 0x37, 0x4b, 0xd7, 0x7d, 0xcb, 0x81, 0xd1, 0xd9, 0x86, 0x4f, 0x82, 0x64, 0x96, 0x44, 0x09, 0x5b, - 0xb8, 0x1a, 0x8c, 0x57, 0x14, 0xe4, 0x5e, 0x96, 0x8e, 0xed, 0xd6, 0xd9, 0x0c, 0x09, 0xdc, 0x41, - 0x14, 0x55, 0x61, 0x8c, 0xc3, 0xd2, 0xb7, 0xe2, 0x48, 0xeb, 0xc7, 0x9c, 0x9d, 0xb3, 0x26, 0x05, - 0x9c, 0x25, 0xe9, 0xfe, 0xd4, 0x81, 0xf3, 0xb3, 0x8d, 0x76, 0x9c, 0x90, 0xe8, 0xa6, 0x90, 0x46, - 0x52, 0x5b, 0x45, 0x1f, 0x81, 0x81, 0xa6, 0x0c, 0xc0, 0x3a, 0x77, 0xd9, 0xc0, 0x4c, 0x9e, 0x51, - 0x6c, 0x3a, 0x98, 0xd5, 0x8d, 0x57, 0x49, 0x25, 0x59, 0x21, 0x89, 0x97, 0x66, 0x0b, 0xa4, 0x30, - 0xac, 0xa8, 0xa2, 0x16, 0xf4, 0xc6, 0x2d, 0x52, 0xb1, 0x97, 0xac, 0x25, 0xe7, 0x50, 0x6e, 0x91, - 0x4a, 0x2a, 0xd7, 0x59, 0xe8, 0x90, 0x71, 0x72, 0xff, 0xb7, 0x03, 0x8f, 0x74, 0x99, 0xef, 0xb2, - 0x1f, 0x27, 0xe8, 0x95, 0x8e, 0x39, 0x4f, 0x1d, 0x6e, 0xce, 0xb4, 0x37, 0x9b, 0xb1, 0x12, 0x08, - 0x12, 0xa2, 0xcd, 0xf7, 0x63, 0x50, 0xf4, 0x13, 0xd2, 0x94, 0x5e, 0x65, 0x0b, 0xfe, 0x9f, 0x2e, - 0x73, 0x99, 0x19, 0x91, 0x29, 0x7b, 0x8b, 0x94, 0x1f, 0xe6, 0x6c, 0xdd, 0x2d, 0xe8, 0x9b, 0x0d, - 0x1b, 0xed, 0x66, 0x70, 0xb8, 0xc4, 0x97, 0x64, 0xb7, 0x45, 0xb2, 0x67, 0x24, 0xd3, 0xe6, 0x59, - 0x8b, 0xf4, 0x03, 0xf5, 0xe4, 0xfb, 0x81, 0xdc, 0x7f, 0xe5, 0x00, 0x7d, 0xab, 0xaa, 0xbe, 0x08, - 0x0c, 0x72, 0x72, 0x9c, 0xe1, 0x63, 0x3a, 0xb9, 0x3b, 0x7b, 0x93, 0x23, 0x0a, 0x51, 0xa3, 0xff, - 0x21, 0xe8, 0x8b, 0x99, 0x85, 0x2d, 0xc6, 0x30, 0x2f, 0xd5, 0x61, 0x6e, 0x77, 0xdf, 0xd9, 0x9b, - 0x3c, 0x54, 0x16, 0xe6, 0x94, 0xa2, 0x2d, 0x62, 0x98, 0x82, 0x2a, 0xd5, 0xdf, 0x9a, 0x24, 0x8e, - 0xbd, 0x9a, 0x34, 0xd8, 0x94, 0xfe, 0xb6, 0xc2, 0xc1, 0x58, 0xb6, 0xbb, 0x5f, 0x76, 0x60, 0x44, - 0x1d, 0x5e, 0x54, 0x1b, 0x47, 0xd7, 0xf4, 0x63, 0x8e, 0xef, 0x94, 0xc7, 0xba, 0x48, 0x1c, 0x71, - 0x90, 0x1f, 0x7c, 0x0a, 0xbe, 0x0b, 0x86, 0xab, 0xa4, 0x45, 0x82, 0x2a, 0x09, 0x2a, 0xd4, 0x9a, - 0xa6, 0x3b, 0x64, 0x70, 0x66, 0x9c, 0x9a, 0x8f, 0x73, 0x1a, 0x1c, 0x1b, 0x58, 0xee, 0x37, 0x1d, - 0x78, 0x58, 0x91, 0x2b, 0x93, 0x04, 0x93, 0x24, 0xda, 0x55, 0x59, 0x97, 0x47, 0x3b, 0xad, 0x6e, - 0x52, 0x75, 0x36, 0x89, 0x38, 0xf3, 0x7b, 0x3b, 0xae, 0x86, 0xb8, 0xf2, 0xcb, 0x88, 0x60, 0x49, - 0xcd, 0xfd, 0xd5, 0x1e, 0x38, 0xa3, 0x0f, 0x52, 0x09, 0x98, 0x5f, 0x76, 0x00, 0xd4, 0x0a, 0xd0, - 0x03, 0xb9, 0xc7, 0x4e, 0x28, 0xca, 0x78, 0x52, 0xa9, 0x08, 0x52, 0xe0, 0x18, 0x6b, 0x6c, 0xd1, - 0x4b, 0x30, 0xbc, 0x4d, 0x5f, 0x0a, 0xb2, 0x42, 0xd5, 0x85, 0xb8, 0xd4, 0xc3, 0x86, 0x31, 0x99, - 0xf7, 0x30, 0x6f, 0xa4, 0x78, 0xa9, 0x75, 0xaf, 0x01, 0x63, 0x6c, 0x90, 0xa2, 0x86, 0xcb, 0x48, - 0xa4, 0x3f, 0x12, 0xe1, 0xe2, 0xfe, 0xa0, 0xc5, 0x39, 0x66, 0x9f, 0xfa, 0xcc, 0xa9, 0xfd, 0xbd, - 0xc9, 0x11, 0x03, 0x84, 0xcd, 0x41, 0xb8, 0x2f, 0x01, 0x5b, 0x0b, 0x3f, 0x68, 0x93, 0xd5, 0x00, - 0x3d, 0x21, 0x5d, 0x6e, 0x3c, 0x4c, 0xa2, 0x24, 0x87, 0xee, 0x76, 0xa3, 0xa6, 0xe9, 0xa6, 0xe7, - 0x37, 0x58, 0x36, 0x22, 0xc5, 0x52, 0xa6, 0xe9, 0x3c, 0x83, 0x62, 0xd1, 0xea, 0x4e, 0x41, 0xff, - 0x2c, 0x9d, 0x3b, 0x89, 0x28, 0x5d, 0x3d, 0x89, 0x78, 0xc4, 0x48, 0x22, 0x96, 0xc9, 0xc2, 0xeb, - 0x70, 0x76, 0x36, 0x22, 0x5e, 0x42, 0xca, 0x97, 0x67, 0xda, 0x95, 0x2d, 0x92, 0xf0, 0x4c, 0xad, - 0x18, 0xbd, 0x17, 0x46, 0x42, 0x76, 0x64, 0x2c, 0x87, 0x95, 0x2d, 0x3f, 0xa8, 0x09, 0x0f, 0xea, - 0x59, 0x41, 0x65, 0x64, 0x55, 0x6f, 0xc4, 0x26, 0xae, 0xfb, 0x9f, 0x0a, 0x30, 0x3c, 0x1b, 0x85, - 0x81, 0x14, 0x8b, 0x27, 0x70, 0x94, 0x25, 0xc6, 0x51, 0x66, 0x21, 0x7a, 0xa9, 0x8f, 0xbf, 0xdb, - 0x71, 0x86, 0x6e, 0x2b, 0x11, 0xd9, 0x63, 0xcb, 0x04, 0x31, 0xf8, 0x32, 0xda, 0xe9, 0xc3, 0x36, - 0x05, 0xa8, 0xfb, 0x9f, 0x1d, 0x18, 0xd7, 0xd1, 0x4f, 0xe0, 0x04, 0x8d, 0xcd, 0x13, 0xf4, 0x9a, - 0xdd, 0xf9, 0x76, 0x39, 0x36, 0x3f, 0xdf, 0x67, 0xce, 0x93, 0x85, 0xae, 0xbf, 0xea, 0xc0, 0xf0, - 0x8e, 0x06, 0x10, 0x93, 0xb5, 0xad, 0xc4, 0xbc, 0x43, 0x8a, 0x19, 0x1d, 0x7a, 0x27, 0xf3, 0x1b, - 0x1b, 0x23, 0xa1, 0x72, 0x3f, 0xae, 0xd4, 0x49, 0xb5, 0xdd, 0x90, 0xc7, 0xb7, 0x5a, 0xd2, 0xb2, - 0x80, 0x63, 0x85, 0x81, 0x5e, 0x81, 0x53, 0x95, 0x30, 0xa8, 0xb4, 0xa3, 0x88, 0x04, 0x95, 0xdd, - 0x35, 0x76, 0xe5, 0x41, 0x1c, 0x88, 0x53, 0xa2, 0xdb, 0xa9, 0xd9, 0x2c, 0xc2, 0x9d, 0x3c, 0x20, - 0xee, 0x24, 0xc4, 0x7d, 0xff, 0x31, 0x3d, 0xb2, 0x84, 0xc1, 0xa5, 0xf9, 0xfe, 0x19, 0x18, 0xcb, - 0x76, 0x74, 0x1d, 0xce, 0xc7, 0x89, 0x17, 0x25, 0x7e, 0x50, 0x9b, 0x23, 0x5e, 0xb5, 0xe1, 0x07, - 0xd4, 0x94, 0x08, 0x83, 0x2a, 0x8f, 0x0c, 0xf6, 0xcc, 0x3c, 0xb2, 0xbf, 0x37, 0x79, 0xbe, 0x9c, - 0x8f, 0x82, 0xbb, 0xf5, 0x45, 0x1f, 0x82, 0x09, 0x11, 0x5d, 0xd8, 0x6c, 0x37, 0x5e, 0x08, 0x37, - 0xe2, 0xab, 0x7e, 0x4c, 0xed, 0xf8, 0x65, 0xbf, 0xe9, 0x27, 0x2c, 0xfe, 0x57, 0x9c, 0xb9, 0xb0, - 0xbf, 0x37, 0x39, 0x51, 0xee, 0x8a, 0x85, 0x0f, 0xa0, 0x80, 0x30, 0x9c, 0xe3, 0xc2, 0xaf, 0x83, - 0x76, 0x3f, 0xa3, 0x3d, 0xb1, 0xbf, 0x37, 0x79, 0x6e, 0x3e, 0x17, 0x03, 0x77, 0xe9, 0x49, 0x9f, - 0x60, 0xe2, 0x37, 0xc9, 0x6b, 0x61, 0x40, 0x58, 0xde, 0x89, 0xf6, 0x04, 0xd7, 0x05, 0x1c, 0x2b, - 0x0c, 0xf4, 0x6a, 0xba, 0x13, 0xe9, 0xeb, 0x22, 0xf2, 0x47, 0x8e, 0x2e, 0xe1, 0x98, 0x69, 0x72, - 0x53, 0xa3, 0xc4, 0x12, 0x23, 0x0d, 0xda, 0xee, 0x1f, 0x14, 0x00, 0x75, 0x8a, 0x08, 0xb4, 0x04, - 0x7d, 0x5e, 0x25, 0xf1, 0xb7, 0x65, 0xa2, 0xdd, 0x13, 0x79, 0xc7, 0x27, 0x67, 0x85, 0xc9, 0x26, - 0xa1, 0x3b, 0x84, 0xa4, 0x72, 0x65, 0x9a, 0x75, 0xc5, 0x82, 0x04, 0x0a, 0xe1, 0x54, 0xc3, 0x8b, - 0x13, 0xb9, 0x57, 0xab, 0x74, 0xca, 0x42, 0xb0, 0xfe, 0xfc, 0xe1, 0x26, 0x45, 0x7b, 0xcc, 0x9c, - 0xa5, 0x3b, 0x77, 0x39, 0x4b, 0x08, 0x77, 0xd2, 0x46, 0x1f, 0x67, 0x7a, 0x08, 0x57, 0x12, 0xa5, - 0x02, 0xb0, 0x64, 0xe5, 0x8c, 0xe6, 0x34, 0x0d, 0x1d, 0x44, 0xb0, 0xc1, 0x1a, 0x4b, 0xf7, 0x5f, - 0x03, 0xf4, 0xcf, 0x4d, 0x2f, 0xac, 0x7b, 0xf1, 0xd6, 0x21, 0x54, 0x73, 0xba, 0x3b, 0x84, 0x0e, - 0x95, 0x7d, 0xbf, 0xa5, 0x6e, 0x85, 0x15, 0x06, 0x0a, 0xa0, 0xcf, 0x0f, 0xe8, 0x0b, 0x51, 0x1a, - 0xb5, 0xe5, 0xcd, 0x56, 0x66, 0x06, 0xf3, 0x4f, 0x2c, 0x32, 0xea, 0x58, 0x70, 0x41, 0xb7, 0x61, - 0xd0, 0x93, 0x17, 0x55, 0xc4, 0xb1, 0xb4, 0x64, 0xc3, 0x4d, 0x2b, 0x48, 0xea, 0x89, 0x32, 0x02, - 0x84, 0x53, 0x86, 0xe8, 0x13, 0x0e, 0x0c, 0xc9, 0xa9, 0x63, 0xb2, 0x29, 0x22, 0xa8, 0x2b, 0xf6, - 0xe6, 0x8c, 0xc9, 0x26, 0xcf, 0xa2, 0xd0, 0x00, 0x58, 0x67, 0xd9, 0xa1, 0xca, 0x17, 0x0f, 0xa3, - 0xca, 0xa3, 0x1d, 0x18, 0xdc, 0xf1, 0x93, 0x3a, 0x3b, 0x78, 0x44, 0xe4, 0x66, 0xfe, 0xfe, 0x47, - 0x4d, 0xc9, 0xa5, 0x2b, 0x76, 0x53, 0x32, 0xc0, 0x29, 0x2f, 0x74, 0x91, 0x33, 0x66, 0x17, 0x7d, - 0x98, 0xc8, 0x1a, 0x34, 0x3b, 0xb0, 0x06, 0x9c, 0xe2, 0xd0, 0x25, 0x1e, 0xa6, 0xbf, 0xca, 0xe4, - 0xa3, 0x6d, 0xfa, 0x1e, 0x8b, 0xcc, 0x38, 0x0b, 0xfb, 0x4a, 0x52, 0xe4, 0x8b, 0x75, 0x53, 0xe3, - 0x81, 0x0d, 0x8e, 0xf4, 0x1d, 0xd9, 0xa9, 0x93, 0x40, 0x64, 0xee, 0xab, 0x77, 0xe4, 0x66, 0x9d, - 0x04, 0x98, 0xb5, 0xa0, 0xdb, 0xdc, 0xb4, 0xe0, 0x3a, 0xae, 0xc8, 0x72, 0x5b, 0xb6, 0xa3, 0x76, - 0x73, 0x9a, 0x3c, 0x79, 0x3e, 0xfd, 0x8d, 0x35, 0x7e, 0x54, 0x5d, 0x0e, 0x83, 0x2b, 0xb7, 0xfc, - 0x44, 0xa4, 0xfc, 0x2b, 0x49, 0xb7, 0xca, 0xa0, 0x58, 0xb4, 0xf2, 0x0c, 0x01, 0xba, 0x09, 0x62, - 0x96, 0xdf, 0x3f, 0xa8, 0x67, 0x08, 0x30, 0x30, 0x96, 0xed, 0xe8, 0xef, 0x39, 0x50, 0xac, 0x87, - 0xe1, 0x56, 0x5c, 0x1a, 0x61, 0x9b, 0xc3, 0x82, 0xaa, 0x27, 0x24, 0xce, 0xd4, 0x55, 0x4a, 0xd6, - 0xbc, 0xc4, 0x54, 0x64, 0xb0, 0x3b, 0x7b, 0x93, 0xa3, 0xcb, 0xfe, 0x26, 0xa9, 0xec, 0x56, 0x1a, - 0x84, 0x41, 0x3e, 0xf9, 0x96, 0x06, 0xb9, 0xb2, 0x4d, 0x82, 0x04, 0xf3, 0x51, 0x4d, 0x7c, 0xde, - 0x01, 0x48, 0x09, 0xe5, 0x84, 0xe2, 0x88, 0x19, 0xbc, 0xb6, 0x60, 0xe7, 0x19, 0x43, 0xd3, 0x63, - 0x7b, 0xff, 0xc6, 0x81, 0x21, 0x3a, 0x39, 0x29, 0x02, 0x9f, 0x82, 0xbe, 0xc4, 0x8b, 0x6a, 0x44, - 0xfa, 0xaf, 0xd5, 0xe3, 0x58, 0x67, 0x50, 0x2c, 0x5a, 0x51, 0x00, 0xc5, 0xc4, 0x8b, 0xb7, 0xa4, - 0x76, 0xb9, 0x68, 0x6d, 0x89, 0x53, 0xc5, 0x92, 0xfe, 0x8a, 0x31, 0x67, 0x83, 0x9e, 0x86, 0x01, - 0xaa, 0x00, 0xcc, 0x7b, 0xb1, 0xcc, 0x10, 0x19, 0xa6, 0x42, 0x7c, 0x5e, 0xc0, 0xb0, 0x6a, 0x75, - 0x7f, 0xbd, 0x00, 0xbd, 0x73, 0xdc, 0xce, 0xe8, 0x8b, 0xc3, 0x76, 0x54, 0x21, 0x42, 0xdf, 0xb4, - 0xb0, 0xa7, 0x29, 0xdd, 0x32, 0xa3, 0xa9, 0x69, 0xfa, 0xec, 0x37, 0x16, 0xbc, 0xa8, 0x21, 0x3b, - 0x9a, 0x44, 0x5e, 0x10, 0x6f, 0xb2, 0x48, 0x81, 0x1f, 0x06, 0x62, 0x89, 0x2c, 0xec, 0xc2, 0x75, - 0x83, 0x6e, 0x39, 0x21, 0xad, 0x34, 0x60, 0x61, 0xb6, 0xe1, 0xcc, 0x18, 0xdc, 0xdf, 0x70, 0x00, - 0xd2, 0xd1, 0xa3, 0xcf, 0x39, 0x30, 0xe2, 0xe9, 0x99, 0x89, 0x62, 0x8d, 0x56, 0xed, 0x45, 0x09, - 0x19, 0x59, 0x6e, 0x62, 0x1b, 0x20, 0x6c, 0x32, 0x76, 0xdf, 0x0d, 0x45, 0xf6, 0x76, 0x30, 0x5d, - 0x5c, 0xb8, 0x64, 0xb3, 0x3e, 0x18, 0xe9, 0xaa, 0xc5, 0x0a, 0xc3, 0x7d, 0x05, 0x46, 0xaf, 0xdc, - 0x22, 0x95, 0x76, 0x12, 0x46, 0xdc, 0x21, 0xdd, 0xe5, 0x26, 0x8a, 0x73, 0x4f, 0x37, 0x51, 0xbe, - 0xeb, 0xc0, 0x90, 0x96, 0xa6, 0x46, 0x4f, 0xea, 0xda, 0x6c, 0x99, 0xdb, 0xdd, 0x62, 0xa9, 0x96, - 0xac, 0x24, 0xc2, 0x71, 0x92, 0xe9, 0x31, 0xa2, 0x40, 0x38, 0x65, 0x78, 0x97, 0x34, 0x32, 0xf7, - 0x77, 0x1d, 0x38, 0x9b, 0x9b, 0x53, 0xf7, 0x80, 0x87, 0x7d, 0x11, 0x06, 0xb7, 0xc8, 0xae, 0x11, - 0x5f, 0x53, 0x1d, 0x96, 0x64, 0x03, 0x4e, 0x71, 0xdc, 0xef, 0x39, 0x90, 0x52, 0xa2, 0xa2, 0x68, - 0x23, 0x1d, 0xb9, 0x26, 0x8a, 0x04, 0x27, 0xd1, 0x8a, 0x6e, 0xc3, 0x79, 0xf3, 0x09, 0xde, 0x63, - 0x18, 0x80, 0xdb, 0x4c, 0xf9, 0x94, 0x70, 0x37, 0x16, 0xee, 0x0d, 0x28, 0x2e, 0x78, 0xed, 0x1a, - 0x39, 0x94, 0x13, 0x87, 0x8a, 0xb1, 0x88, 0x78, 0x8d, 0x44, 0xaa, 0xe9, 0x42, 0x8c, 0x61, 0x01, - 0xc3, 0xaa, 0xd5, 0xfd, 0x61, 0x11, 0x86, 0xb4, 0x9b, 0x13, 0xf4, 0x1c, 0x8f, 0x48, 0x2b, 0xcc, - 0xea, 0xba, 0xf4, 0x61, 0x63, 0xd6, 0x42, 0xdf, 0x9f, 0x88, 0x6c, 0xfb, 0x31, 0x17, 0x39, 0xc6, - 0xfb, 0x83, 0x05, 0x1c, 0x2b, 0x0c, 0x34, 0x09, 0xc5, 0x2a, 0x69, 0x25, 0x75, 0x26, 0x4d, 0x7b, - 0x79, 0xfa, 0xd8, 0x1c, 0x05, 0x60, 0x0e, 0xa7, 0x08, 0x9b, 0x24, 0xa9, 0xd4, 0x99, 0xb3, 0x51, - 0xe4, 0x97, 0xcd, 0x53, 0x00, 0xe6, 0xf0, 0x9c, 0xc0, 0x58, 0xf1, 0xf8, 0x03, 0x63, 0x7d, 0x96, - 0x03, 0x63, 0xa8, 0x05, 0xa7, 0xe3, 0xb8, 0xbe, 0x16, 0xf9, 0xdb, 0x5e, 0x42, 0xd2, 0x9d, 0xd3, - 0x7f, 0x14, 0x3e, 0xe7, 0xd9, 0x5d, 0xe6, 0xf2, 0xd5, 0x2c, 0x15, 0x9c, 0x47, 0x1a, 0x95, 0xe1, - 0xac, 0x1f, 0xc4, 0xa4, 0xd2, 0x8e, 0xc8, 0x62, 0x2d, 0x08, 0x23, 0x72, 0x35, 0x8c, 0x29, 0x39, - 0x71, 0x13, 0x53, 0x65, 0x5c, 0x2e, 0xe6, 0x21, 0xe1, 0xfc, 0xbe, 0x68, 0x01, 0x4e, 0x55, 0xfd, - 0xd8, 0xdb, 0x68, 0x90, 0x72, 0x7b, 0xa3, 0x19, 0x52, 0x83, 0x8d, 0xdf, 0x8e, 0x18, 0x98, 0x79, - 0x58, 0xba, 0x26, 0xe6, 0xb2, 0x08, 0xb8, 0xb3, 0x0f, 0x7a, 0x1e, 0x86, 0x63, 0x3f, 0xa8, 0x35, - 0xc8, 0x4c, 0xe4, 0x05, 0x95, 0xba, 0xb8, 0xc2, 0xa9, 0x5c, 0xb8, 0x65, 0xad, 0x0d, 0x1b, 0x98, - 0xec, 0x7d, 0xe5, 0x7d, 0x32, 0x9a, 0x9c, 0xc0, 0x16, 0xad, 0xee, 0x8f, 0x1c, 0x18, 0xd6, 0xb3, - 0x9d, 0xa9, 0x96, 0x0c, 0xf5, 0xb9, 0xf9, 0x32, 0x97, 0xe3, 0xf6, 0x4e, 0xeb, 0xab, 0x8a, 0x66, - 0x6a, 0x55, 0xa6, 0x30, 0xac, 0xf1, 0x3c, 0xc4, 0xdd, 0xe5, 0x27, 0xa0, 0xb8, 0x19, 0x52, 0x65, - 0xa2, 0xc7, 0xf4, 0xfd, 0xce, 0x53, 0x20, 0xe6, 0x6d, 0xee, 0xff, 0x74, 0xe0, 0x5c, 0x7e, 0x22, - 0xf7, 0xdb, 0x61, 0x92, 0x97, 0x00, 0xe8, 0x54, 0x0c, 0x81, 0xac, 0x55, 0x2f, 0x90, 0x2d, 0x58, - 0xc3, 0x3a, 0xdc, 0xb4, 0xff, 0x98, 0x2a, 0xb4, 0x29, 0x9f, 0x2f, 0x38, 0x30, 0x42, 0xd9, 0x2e, - 0x45, 0x1b, 0xc6, 0x6c, 0x57, 0xed, 0xcc, 0x56, 0x91, 0x4d, 0x5d, 0xdc, 0x06, 0x18, 0x9b, 0xcc, - 0xd1, 0x2f, 0xc0, 0xa0, 0x57, 0xad, 0x46, 0x24, 0x8e, 0x55, 0xb0, 0x88, 0xc5, 0xb1, 0xa7, 0x25, - 0x10, 0xa7, 0xed, 0x54, 0x88, 0xd6, 0xab, 0x9b, 0x31, 0x95, 0x4b, 0xc2, 0xb3, 0xa7, 0x84, 0x28, - 0x65, 0x42, 0xe1, 0x58, 0x61, 0xb8, 0x7f, 0xb3, 0x17, 0x4c, 0xde, 0xa8, 0x0a, 0x63, 0x5b, 0xd1, - 0xc6, 0x2c, 0x8b, 0xb5, 0xdf, 0x4b, 0xcc, 0x9b, 0xc5, 0xa2, 0x97, 0x4c, 0x0a, 0x38, 0x4b, 0x52, - 0x70, 0x59, 0x22, 0xbb, 0x89, 0xb7, 0x71, 0xcf, 0x11, 0xef, 0x25, 0x93, 0x02, 0xce, 0x92, 0x44, - 0xef, 0x86, 0xa1, 0xad, 0x68, 0x43, 0x8a, 0xe8, 0x6c, 0xfa, 0xc4, 0x52, 0xda, 0x84, 0x75, 0x3c, - 0xba, 0x84, 0x5b, 0xd1, 0x06, 0x3d, 0xd2, 0xe4, 0x5d, 0x7e, 0xb5, 0x84, 0x4b, 0x02, 0x8e, 0x15, - 0x06, 0x6a, 0x01, 0xda, 0x92, 0xab, 0xa7, 0x32, 0x0b, 0xc4, 0x49, 0x72, 0xf8, 0xc4, 0x04, 0x96, - 0xa1, 0xbd, 0xd4, 0x41, 0x07, 0xe7, 0xd0, 0x46, 0x2f, 0xc1, 0xf9, 0xad, 0x68, 0x43, 0x1c, 0xf4, - 0x6b, 0x91, 0x1f, 0x54, 0xfc, 0x96, 0x71, 0x6f, 0x7f, 0x52, 0x0c, 0xf7, 0xfc, 0x52, 0x3e, 0x1a, - 0xee, 0xd6, 0xdf, 0xfd, 0xad, 0x5e, 0x60, 0x37, 0x0e, 0xa9, 0x2c, 0x6c, 0x92, 0xa4, 0x1e, 0x56, - 0xb3, 0xba, 0xcb, 0x0a, 0x83, 0x62, 0xd1, 0x2a, 0xf3, 0x10, 0x0b, 0x5d, 0xf2, 0x10, 0x77, 0xa0, - 0xbf, 0x4e, 0xbc, 0x2a, 0x89, 0xa4, 0xab, 0x6d, 0xd9, 0xce, 0x1d, 0xc9, 0xab, 0x8c, 0x68, 0x6a, - 0x42, 0xf3, 0xdf, 0x31, 0x96, 0xdc, 0xd0, 0x7b, 0x60, 0x94, 0x6a, 0x21, 0x61, 0x3b, 0x91, 0x7e, - 0xe5, 0x5e, 0xe6, 0x57, 0x66, 0x27, 0xea, 0xba, 0xd1, 0x82, 0x33, 0x98, 0x68, 0x0e, 0xc6, 0x85, - 0x0f, 0x58, 0xb9, 0xf0, 0xc4, 0xc2, 0xaa, 0x82, 0x0a, 0xe5, 0x4c, 0x3b, 0xee, 0xe8, 0xc1, 0x12, - 0xcf, 0xc2, 0x2a, 0x0f, 0x03, 0xea, 0x89, 0x67, 0x61, 0x75, 0x17, 0xb3, 0x16, 0xf4, 0x1a, 0x0c, - 0xd0, 0xbf, 0xf3, 0x51, 0xd8, 0x14, 0x7e, 0x95, 0x35, 0x3b, 0xab, 0x43, 0x79, 0x08, 0x2b, 0x8f, - 0x69, 0x67, 0x33, 0x82, 0x0b, 0x56, 0xfc, 0xa8, 0xad, 0x21, 0xcf, 0xe1, 0xf2, 0x96, 0xdf, 0xba, - 0x41, 0x22, 0x7f, 0x73, 0x97, 0x29, 0x0d, 0x03, 0xa9, 0xad, 0xb1, 0xd8, 0x81, 0x81, 0x73, 0x7a, - 0xb9, 0x5f, 0x28, 0xc0, 0xb0, 0x7e, 0x71, 0xf5, 0x6e, 0xc9, 0xa9, 0x71, 0xba, 0x29, 0xb8, 0x65, - 0x79, 0xd5, 0xc2, 0xb4, 0xef, 0xb6, 0x21, 0xea, 0xd0, 0xeb, 0xb5, 0x85, 0xb6, 0x68, 0xc5, 0x81, - 0xc5, 0x66, 0xdc, 0x4e, 0xea, 0xfc, 0x86, 0x13, 0x4b, 0x1b, 0x65, 0x1c, 0xdc, 0x4f, 0xf7, 0xc0, - 0x80, 0x6c, 0x44, 0x9f, 0x72, 0x00, 0xd2, 0x7c, 0x1f, 0x21, 0x4a, 0xd7, 0x6c, 0x24, 0x83, 0xe8, - 0xa9, 0x4a, 0x9a, 0xd3, 0x59, 0xc1, 0xb1, 0xc6, 0x17, 0x25, 0xd0, 0x17, 0xd2, 0xc1, 0x5d, 0xb2, - 0x77, 0xf9, 0x7a, 0x95, 0x32, 0xbe, 0xc4, 0xb8, 0xa7, 0x2e, 0x2f, 0x06, 0xc3, 0x82, 0x17, 0xb5, - 0xde, 0x36, 0x64, 0x1a, 0x9a, 0x3d, 0xf7, 0xb0, 0xca, 0x6c, 0x4b, 0x8d, 0x31, 0x05, 0xc2, 0x29, - 0x43, 0xf7, 0x39, 0x18, 0x35, 0x5f, 0x06, 0x6a, 0x11, 0x6c, 0xec, 0x26, 0x84, 0xfb, 0x0a, 0x86, - 0xb9, 0x45, 0x30, 0x43, 0x01, 0x98, 0xc3, 0xdd, 0x37, 0xa9, 0x1e, 0xa0, 0xc4, 0xcb, 0x21, 0xdc, - 0xf3, 0x4f, 0xe8, 0x8e, 0xae, 0x6e, 0x36, 0xd3, 0xc7, 0x61, 0x90, 0xfd, 0xc3, 0x5e, 0xf4, 0x1e, - 0x5b, 0x41, 0xe3, 0x74, 0x9c, 0xe2, 0x55, 0x67, 0x3a, 0xc1, 0x0d, 0xc9, 0x08, 0xa7, 0x3c, 0xdd, - 0x10, 0xc6, 0xb3, 0xd8, 0xe8, 0x83, 0x30, 0x1c, 0xcb, 0x63, 0x35, 0xbd, 0x86, 0x75, 0xc8, 0xe3, - 0x97, 0xf9, 0x6c, 0xcb, 0x5a, 0x77, 0x6c, 0x10, 0x73, 0x57, 0xa1, 0xcf, 0xea, 0x12, 0xba, 0xdf, - 0x76, 0x60, 0x90, 0x45, 0xcd, 0x6a, 0x91, 0xd7, 0x4c, 0xbb, 0xf4, 0x1c, 0xb0, 0xea, 0x31, 0xf4, - 0x73, 0xfb, 0x5a, 0x66, 0x9b, 0x58, 0x90, 0x32, 0xbc, 0x66, 0x5a, 0x2a, 0x65, 0xb8, 0x21, 0x1f, - 0x63, 0xc9, 0xc9, 0xfd, 0x4c, 0x01, 0xfa, 0x16, 0x83, 0x56, 0xfb, 0xcf, 0x7d, 0xdd, 0xae, 0x15, - 0xe8, 0x5d, 0x4c, 0x48, 0xd3, 0x2c, 0x2f, 0x37, 0x3c, 0xf3, 0xa4, 0x5e, 0x5a, 0xae, 0x64, 0x96, - 0x96, 0xc3, 0xde, 0x8e, 0x4c, 0xc6, 0x12, 0xfe, 0xdd, 0xf4, 0x2a, 0xda, 0xb3, 0x30, 0xb8, 0xec, - 0x6d, 0x90, 0xc6, 0x12, 0xd9, 0x65, 0x17, 0xc7, 0x78, 0x62, 0x80, 0x93, 0x1a, 0xf6, 0x46, 0x10, - 0x7f, 0x0e, 0x46, 0x19, 0xb6, 0x7a, 0x19, 0xa8, 0xe5, 0x40, 0xd2, 0xda, 0x3c, 0x8e, 0x69, 0x39, - 0x68, 0x75, 0x79, 0x34, 0x2c, 0x77, 0x0a, 0x86, 0x52, 0x2a, 0x87, 0xe0, 0xfa, 0xb3, 0x02, 0x8c, - 0x18, 0x6e, 0x6a, 0x23, 0x78, 0xe7, 0xdc, 0x35, 0x78, 0x67, 0x04, 0xd3, 0x0a, 0x0f, 0x3a, 0x98, - 0xd6, 0x73, 0xf2, 0xc1, 0x34, 0xf3, 0x21, 0xf5, 0x1e, 0xea, 0x21, 0x35, 0xa0, 0x77, 0xd9, 0x0f, - 0xb6, 0x0e, 0x27, 0x67, 0xe2, 0x4a, 0xd8, 0xea, 0x90, 0x33, 0x65, 0x0a, 0xc4, 0xbc, 0x4d, 0x6a, - 0x2e, 0x3d, 0xf9, 0x9a, 0x8b, 0xfb, 0x29, 0x07, 0x86, 0x57, 0xbc, 0xc0, 0xdf, 0x24, 0x71, 0xc2, - 0xf6, 0x55, 0x72, 0xac, 0x17, 0x88, 0x86, 0xbb, 0x5c, 0x85, 0xff, 0xa4, 0x03, 0xa7, 0x56, 0x48, - 0x33, 0xf4, 0x5f, 0xf3, 0xd2, 0x5c, 0x47, 0x3a, 0xf6, 0xba, 0x9f, 0x88, 0xd4, 0x2e, 0x35, 0xf6, - 0xab, 0x7e, 0x82, 0x29, 0xfc, 0x2e, 0x3e, 0x58, 0x96, 0xcb, 0x4f, 0x0d, 0x34, 0xed, 0x52, 0x5b, - 0x9a, 0xc5, 0x28, 0x1b, 0x70, 0x8a, 0xe3, 0xfe, 0xb6, 0x03, 0xfd, 0x7c, 0x10, 0x2a, 0x3d, 0xd4, - 0xe9, 0x42, 0xbb, 0x0e, 0x45, 0xd6, 0x4f, 0xec, 0xea, 0x05, 0x0b, 0xea, 0x0f, 0x25, 0xc7, 0xdf, - 0x41, 0xf6, 0x2f, 0xe6, 0x0c, 0x98, 0xd9, 0xe2, 0xdd, 0x9a, 0x56, 0x69, 0x9e, 0xa9, 0xd9, 0xc2, - 0xa0, 0x58, 0xb4, 0xba, 0x5f, 0xef, 0x81, 0x01, 0x55, 0x01, 0x8a, 0xdd, 0xcf, 0x0f, 0x82, 0x30, - 0xf1, 0x78, 0x52, 0x00, 0x97, 0xd5, 0x1f, 0xb4, 0x57, 0x81, 0x6a, 0x6a, 0x3a, 0xa5, 0xce, 0x63, - 0x6f, 0xca, 0x08, 0xd5, 0x5a, 0xb0, 0x3e, 0x08, 0xf4, 0x31, 0xe8, 0x6b, 0x50, 0xe9, 0x23, 0x45, - 0xf7, 0x0d, 0x8b, 0xc3, 0x61, 0x62, 0x4d, 0x8c, 0x44, 0xad, 0x10, 0x07, 0x62, 0xc1, 0x75, 0xe2, - 0x7d, 0x30, 0x9e, 0x1d, 0xf5, 0xdd, 0xee, 0xdc, 0x0d, 0xea, 0x37, 0xf6, 0xfe, 0xb2, 0x90, 0x9e, - 0x47, 0xef, 0xea, 0xbe, 0x08, 0x43, 0x2b, 0x24, 0x89, 0xfc, 0x0a, 0x23, 0x70, 0xb7, 0xcd, 0x75, - 0x28, 0xfd, 0xe1, 0xb3, 0x6c, 0xb3, 0x52, 0x9a, 0x31, 0xba, 0x0d, 0xd0, 0x8a, 0x42, 0x6a, 0xbf, - 0x92, 0xb6, 0x7c, 0xd8, 0x16, 0xf4, 0xe1, 0x35, 0x45, 0x93, 0x87, 0x8b, 0xd3, 0xdf, 0x58, 0xe3, - 0xe7, 0x3e, 0x03, 0xc5, 0x95, 0x76, 0x42, 0x6e, 0xdd, 0x5d, 0x62, 0xb9, 0x1f, 0x84, 0x61, 0x86, - 0x7a, 0x35, 0x6c, 0xd0, 0x53, 0x92, 0xce, 0xb4, 0x49, 0x7f, 0x67, 0x1d, 0xf4, 0x0c, 0x09, 0xf3, - 0x36, 0xfa, 0x06, 0xd4, 0xc3, 0x46, 0x55, 0x5d, 0xc8, 0x51, 0xcf, 0xf7, 0x2a, 0x83, 0x62, 0xd1, - 0xea, 0xfe, 0x72, 0x01, 0x86, 0x58, 0x47, 0x21, 0x3d, 0x76, 0xa1, 0xbf, 0xce, 0xf9, 0x88, 0x25, - 0xb1, 0x90, 0xdd, 0xa6, 0x8f, 0x5e, 0x33, 0xcd, 0x38, 0x00, 0x4b, 0x7e, 0x94, 0xf5, 0x8e, 0xe7, - 0x27, 0x94, 0x75, 0xe1, 0x78, 0x59, 0xdf, 0xe4, 0x6c, 0xb0, 0xe4, 0xe7, 0x7e, 0xb9, 0x00, 0xc0, - 0xea, 0x73, 0xf1, 0xfb, 0xa0, 0xbf, 0x08, 0xc5, 0x56, 0xdd, 0x8b, 0xb3, 0x41, 0xb7, 0xe2, 0x1a, - 0x05, 0xde, 0x11, 0x37, 0x5e, 0xd9, 0x0f, 0xcc, 0x11, 0xf5, 0xc4, 0xf2, 0xc2, 0xc1, 0x89, 0xe5, - 0xa8, 0x05, 0xfd, 0x61, 0x3b, 0xa1, 0xba, 0xa1, 0x38, 0x5c, 0x2d, 0xc4, 0x9c, 0x57, 0x39, 0x41, - 0x9e, 0x8d, 0x2d, 0x7e, 0x60, 0xc9, 0x06, 0x3d, 0x0f, 0x03, 0xad, 0x28, 0xac, 0xd1, 0xb3, 0x52, - 0x1c, 0xa7, 0x8f, 0x4a, 0xfd, 0x63, 0x4d, 0xc0, 0xef, 0x68, 0xff, 0x63, 0x85, 0xed, 0xfe, 0x64, - 0x8c, 0xaf, 0x8b, 0xd8, 0x1c, 0x13, 0x50, 0xf0, 0xa5, 0x27, 0x08, 0x04, 0x89, 0xc2, 0xe2, 0x1c, - 0x2e, 0xf8, 0x55, 0xb5, 0x8f, 0x0b, 0x5d, 0x4f, 0xde, 0x77, 0xc3, 0x50, 0xd5, 0x8f, 0x5b, 0x0d, - 0x6f, 0xf7, 0x5a, 0x8e, 0x1b, 0x6e, 0x2e, 0x6d, 0xc2, 0x3a, 0x1e, 0x7a, 0x56, 0x5c, 0x23, 0xe8, - 0x35, 0x5c, 0x2f, 0xf2, 0x1a, 0x41, 0x7a, 0xdf, 0x98, 0xdf, 0x20, 0xc8, 0xde, 0xcb, 0x2e, 0x1e, - 0xfa, 0x5e, 0x76, 0x56, 0xf3, 0xe9, 0x3b, 0x79, 0xcd, 0xe7, 0xbd, 0x30, 0x22, 0x7f, 0x32, 0x75, - 0xa4, 0x74, 0x86, 0x8d, 0x5e, 0xb9, 0x87, 0xd7, 0xf5, 0x46, 0x6c, 0xe2, 0xa6, 0x9b, 0xb6, 0xff, - 0xb0, 0x9b, 0xf6, 0x12, 0xc0, 0x46, 0xd8, 0x0e, 0xaa, 0x5e, 0xb4, 0xbb, 0x38, 0x27, 0x92, 0x0e, - 0x95, 0xa2, 0x35, 0xa3, 0x5a, 0xb0, 0x86, 0xa5, 0x6f, 0xf4, 0xc1, 0xbb, 0x6c, 0xf4, 0x0f, 0xc2, - 0x20, 0x4b, 0xd0, 0x24, 0xd5, 0xe9, 0x44, 0xa4, 0xe3, 0x1c, 0x25, 0x97, 0x4f, 0xa9, 0x1d, 0x65, - 0x49, 0x04, 0xa7, 0xf4, 0xd0, 0x87, 0x00, 0x36, 0xfd, 0xc0, 0x8f, 0xeb, 0x8c, 0xfa, 0xd0, 0x91, - 0xa9, 0xab, 0x79, 0xce, 0x2b, 0x2a, 0x58, 0xa3, 0x88, 0x5e, 0x81, 0x53, 0x24, 0x4e, 0xfc, 0xa6, - 0x97, 0x90, 0xaa, 0xba, 0x78, 0x57, 0x62, 0xbe, 0x43, 0x95, 0x22, 0x7b, 0x25, 0x8b, 0x70, 0x27, - 0x0f, 0x88, 0x3b, 0x09, 0x19, 0x6f, 0xe4, 0xc4, 0x51, 0xde, 0x48, 0xf4, 0x27, 0x0e, 0x9c, 0x8a, - 0x08, 0xcf, 0xd1, 0x88, 0xd5, 0xc0, 0xce, 0x32, 0x79, 0x59, 0xb1, 0x51, 0xfa, 0x5a, 0xd5, 0xb8, - 0xc0, 0x59, 0x2e, 0x5c, 0x51, 0x20, 0x72, 0xf6, 0x1d, 0xed, 0x77, 0xf2, 0x80, 0x9f, 0x7c, 0x6b, - 0x72, 0xb2, 0xb3, 0x04, 0xbb, 0x22, 0x4e, 0xdf, 0xbc, 0xbf, 0xf1, 0xd6, 0xe4, 0xb8, 0xfc, 0x9d, - 0x2e, 0x5a, 0xc7, 0x24, 0xe9, 0xb9, 0xd7, 0x0a, 0xab, 0x8b, 0x6b, 0x22, 0x6f, 0x4a, 0x9d, 0x7b, - 0x6b, 0x14, 0x88, 0x79, 0x1b, 0x7a, 0x1a, 0x06, 0xaa, 0x1e, 0x69, 0x86, 0x81, 0x2a, 0x62, 0xca, - 0xb4, 0xe7, 0x39, 0x01, 0xc3, 0xaa, 0x15, 0x35, 0xa0, 0xcf, 0x67, 0x26, 0xba, 0x48, 0x92, 0xb4, - 0xe0, 0x17, 0xe0, 0x26, 0xbf, 0x4c, 0x91, 0x64, 0x42, 0x58, 0xf0, 0xd0, 0xa5, 0xfe, 0xd8, 0xc9, - 0x48, 0xfd, 0xa7, 0x61, 0xa0, 0x52, 0xf7, 0x1b, 0xd5, 0x88, 0x04, 0xa5, 0x71, 0x66, 0xab, 0xb2, - 0x95, 0x98, 0x15, 0x30, 0xac, 0x5a, 0xd1, 0x5f, 0x82, 0x91, 0xb0, 0x9d, 0xb0, 0x97, 0x9c, 0x3e, - 0xff, 0xb8, 0x74, 0x8a, 0xa1, 0xb3, 0x94, 0x97, 0x55, 0xbd, 0x01, 0x9b, 0x78, 0x54, 0xd8, 0xd6, - 0xc3, 0x98, 0x15, 0x46, 0x61, 0xc2, 0xf6, 0x9c, 0x29, 0x6c, 0xaf, 0x6a, 0x6d, 0xd8, 0xc0, 0x44, - 0x5f, 0x75, 0xe0, 0x54, 0x33, 0x6b, 0xba, 0x94, 0xce, 0xb3, 0x95, 0x29, 0xdb, 0x50, 0x71, 0x33, - 0xa4, 0x79, 0x66, 0x70, 0x07, 0x18, 0x77, 0x0e, 0x82, 0x95, 0x28, 0x8a, 0x77, 0x83, 0x4a, 0x3d, - 0x0a, 0x03, 0x73, 0x78, 0x0f, 0xdb, 0xba, 0xc9, 0xc3, 0xde, 0xb2, 0x3c, 0x16, 0x33, 0x0f, 0xef, - 0xef, 0x4d, 0x9e, 0xcd, 0x6d, 0xc2, 0xf9, 0x83, 0x9a, 0x98, 0x83, 0x73, 0xf9, 0x6f, 0xea, 0xdd, - 0x74, 0xed, 0x1e, 0x5d, 0xd7, 0x9e, 0x87, 0x87, 0xbb, 0x0e, 0x8a, 0xca, 0x7c, 0xa9, 0x98, 0x39, - 0xa6, 0xcc, 0xef, 0x50, 0xa4, 0x46, 0x61, 0x58, 0xaf, 0x9e, 0xef, 0xfe, 0xdf, 0x1e, 0x80, 0xd4, - 0x43, 0x8c, 0x3c, 0x18, 0xe5, 0xde, 0xe8, 0xc5, 0xb9, 0x7b, 0xbe, 0x83, 0x3c, 0x6b, 0x10, 0xc0, - 0x19, 0x82, 0xa8, 0x09, 0x88, 0x43, 0xf8, 0xef, 0x7b, 0x89, 0x2a, 0xb2, 0x20, 0xdc, 0x6c, 0x07, - 0x11, 0x9c, 0x43, 0x98, 0xce, 0x28, 0x09, 0xb7, 0x48, 0x70, 0x1d, 0x2f, 0xdf, 0xcb, 0x45, 0x76, - 0x1e, 0x87, 0x32, 0x08, 0xe0, 0x0c, 0x41, 0xe4, 0x42, 0x1f, 0xf3, 0x4a, 0xc8, 0xb4, 0x62, 0x26, - 0x5e, 0xd8, 0x99, 0x1f, 0x63, 0xd1, 0x82, 0xbe, 0xec, 0xc0, 0xa8, 0xbc, 0x8f, 0xcf, 0xfc, 0x80, - 0x32, 0xa1, 0xf8, 0xba, 0x2d, 0x0f, 0xff, 0x15, 0x9d, 0x7a, 0x9a, 0xae, 0x67, 0x80, 0x63, 0x9c, - 0x19, 0x84, 0xfb, 0x12, 0x9c, 0xce, 0xe9, 0x6e, 0xc5, 0x96, 0xfb, 0xae, 0x03, 0x43, 0x5a, 0xd5, - 0x37, 0x74, 0x1b, 0x06, 0xc3, 0xb2, 0xf5, 0x1c, 0xb1, 0xd5, 0x72, 0x47, 0x8e, 0x98, 0x02, 0xe1, - 0x94, 0xe1, 0x61, 0x52, 0xdb, 0x72, 0x4b, 0xd4, 0x3d, 0xe0, 0x61, 0x1f, 0x39, 0xb5, 0xed, 0xdf, - 0xf5, 0x42, 0x4a, 0xe9, 0x88, 0x75, 0x22, 0xd2, 0x44, 0xb8, 0xc2, 0x81, 0x89, 0x70, 0x55, 0x18, - 0xf3, 0x58, 0x14, 0xf5, 0x1e, 0xab, 0x43, 0xf0, 0xa2, 0x9f, 0x26, 0x05, 0x9c, 0x25, 0x49, 0xb9, - 0xc4, 0x69, 0x57, 0xc6, 0xa5, 0xf7, 0xc8, 0x5c, 0xca, 0x26, 0x05, 0x9c, 0x25, 0x89, 0x5e, 0x81, - 0x52, 0x85, 0xdd, 0x76, 0xe4, 0x73, 0x5c, 0xdc, 0xbc, 0x16, 0x26, 0x6b, 0x11, 0x89, 0x49, 0x90, - 0x88, 0xb2, 0x4e, 0x8f, 0x8b, 0x55, 0x28, 0xcd, 0x76, 0xc1, 0xc3, 0x5d, 0x29, 0x50, 0x83, 0x81, - 0x85, 0x61, 0xfd, 0x64, 0x97, 0x09, 0x11, 0x11, 0x9f, 0x56, 0x06, 0x43, 0x59, 0x6f, 0xc4, 0x26, - 0x2e, 0xfa, 0x15, 0x07, 0x46, 0x1a, 0xd2, 0x51, 0x8d, 0xdb, 0x0d, 0x59, 0xa3, 0x10, 0x5b, 0xd9, - 0x7e, 0xcb, 0x3a, 0x65, 0xae, 0x4b, 0x18, 0x20, 0x6c, 0xf2, 0x76, 0xdf, 0x74, 0x60, 0x3c, 0xdb, - 0x0d, 0x6d, 0xc1, 0x63, 0x4d, 0x2f, 0xda, 0x5a, 0x0c, 0x36, 0x23, 0x76, 0x0f, 0x20, 0xe1, 0x4f, - 0x75, 0x7a, 0x33, 0x21, 0xd1, 0x9c, 0xb7, 0xcb, 0x23, 0x78, 0x45, 0xf5, 0xb5, 0x9a, 0xc7, 0x56, - 0x0e, 0x42, 0xc6, 0x07, 0xd3, 0x42, 0x65, 0x38, 0x4b, 0x11, 0x58, 0x85, 0x2d, 0x3f, 0x0c, 0x52, - 0x26, 0x05, 0xc6, 0x44, 0xe5, 0xb3, 0xad, 0xe4, 0x21, 0xe1, 0xfc, 0xbe, 0xee, 0x00, 0xf4, 0xf1, - 0x3b, 0x50, 0xee, 0xbf, 0x2d, 0x80, 0x54, 0xd2, 0xfe, 0x7c, 0x07, 0x85, 0xe8, 0x81, 0x16, 0x31, - 0x47, 0x8b, 0xf0, 0x01, 0xb0, 0x03, 0x4d, 0x94, 0xa3, 0x13, 0x2d, 0x54, 0x7b, 0x25, 0xb7, 0xfc, - 0x64, 0x36, 0xac, 0x4a, 0xcb, 0x9f, 0x69, 0xaf, 0x57, 0x04, 0x0c, 0xab, 0x56, 0xf7, 0x53, 0x0e, - 0x8c, 0xd0, 0x59, 0x36, 0x1a, 0xa4, 0x51, 0x4e, 0x48, 0x2b, 0x46, 0x31, 0x14, 0x63, 0xfa, 0x8f, - 0x3d, 0x0f, 0x56, 0x7a, 0xf5, 0x8d, 0xb4, 0xb4, 0x90, 0x01, 0x65, 0x82, 0x39, 0x2f, 0xf7, 0x3b, - 0x3d, 0x30, 0xa8, 0x16, 0xfb, 0x10, 0x71, 0x88, 0x4b, 0x69, 0xa5, 0x48, 0x2e, 0x0d, 0x4b, 0x5a, - 0x95, 0x48, 0x6a, 0xae, 0x4f, 0x07, 0xbb, 0xfc, 0x8e, 0x7d, 0x5a, 0x32, 0xf2, 0x59, 0x33, 0xe0, - 0x79, 0x4e, 0x8f, 0xa2, 0x69, 0xf8, 0x22, 0xf2, 0x79, 0x4b, 0x8f, 0x37, 0xf7, 0xda, 0x3a, 0x59, - 0x54, 0x30, 0xad, 0x7b, 0xa0, 0x39, 0xf3, 0x11, 0x91, 0xe2, 0xa1, 0x3e, 0x22, 0xf2, 0x0c, 0xf4, - 0x92, 0xa0, 0xdd, 0x64, 0x6a, 0xcb, 0x20, 0x53, 0xd7, 0x7b, 0xaf, 0x04, 0xed, 0xa6, 0x39, 0x33, - 0x86, 0x82, 0xde, 0x07, 0x43, 0x55, 0x12, 0x57, 0x22, 0x9f, 0x5d, 0x1c, 0x17, 0xfe, 0x8e, 0x47, - 0x99, 0x13, 0x29, 0x05, 0x9b, 0x1d, 0xf5, 0x0e, 0xee, 0x6b, 0xd0, 0xb7, 0xd6, 0x68, 0xd7, 0xfc, - 0x00, 0xb5, 0xa0, 0x8f, 0x5f, 0x23, 0x17, 0x27, 0xaf, 0x05, 0x1b, 0x90, 0xbf, 0xed, 0x5a, 0x2e, - 0x04, 0xbf, 0x01, 0x29, 0xf8, 0xb8, 0xff, 0xcc, 0x01, 0x6a, 0xb0, 0x2e, 0xcc, 0xa2, 0xbf, 0xda, - 0xf1, 0xcd, 0x8c, 0x9f, 0xcb, 0xf9, 0x66, 0xc6, 0x08, 0x43, 0xce, 0xf9, 0x5c, 0x46, 0x03, 0x46, - 0x98, 0x8b, 0x5e, 0x9e, 0x47, 0x42, 0xc5, 0xbd, 0x7c, 0xc8, 0x9b, 0xd7, 0x7a, 0x57, 0x21, 0x9d, - 0x75, 0x10, 0x36, 0x89, 0xbb, 0xbf, 0xd3, 0x0b, 0x9a, 0x27, 0xfb, 0x10, 0xdb, 0xfb, 0xa3, 0x99, - 0xb8, 0xc5, 0x8a, 0x95, 0xb8, 0x85, 0x0c, 0x06, 0x70, 0x91, 0x61, 0x86, 0x2a, 0xe8, 0xa0, 0xea, - 0xa4, 0xd1, 0x12, 0x2f, 0x87, 0x1a, 0xd4, 0x55, 0xd2, 0x68, 0x61, 0xd6, 0xa2, 0xee, 0x90, 0xf5, - 0x76, 0xbd, 0x43, 0x56, 0x87, 0x62, 0xcd, 0x6b, 0xd7, 0x88, 0x48, 0xdc, 0xb3, 0x10, 0xa2, 0x62, - 0x49, 0xf5, 0x3c, 0x44, 0xc5, 0xfe, 0xc5, 0x9c, 0x01, 0x7d, 0x3b, 0xeb, 0x32, 0x93, 0x41, 0xf8, - 0x1a, 0x2d, 0xbc, 0x9d, 0x2a, 0x39, 0x82, 0xbf, 0x9d, 0xea, 0x27, 0x4e, 0x99, 0xa1, 0x16, 0xf4, - 0x57, 0x78, 0xc1, 0x06, 0x71, 0xe0, 0x2f, 0xda, 0xb8, 0x24, 0xc7, 0x08, 0x72, 0x57, 0x84, 0xf8, - 0x81, 0x25, 0x1b, 0xf7, 0x22, 0x0c, 0x69, 0xb5, 0xf6, 0xe9, 0x63, 0x50, 0xb5, 0x02, 0xb4, 0xc7, - 0x30, 0xe7, 0x25, 0x1e, 0x66, 0x2d, 0xee, 0x37, 0x7b, 0x41, 0xb9, 0x84, 0xf4, 0x2b, 0x5d, 0x5e, - 0x45, 0xab, 0x6c, 0x62, 0xdc, 0x25, 0x0e, 0x03, 0x2c, 0x5a, 0xa9, 0x52, 0xd4, 0x24, 0x51, 0x4d, - 0x19, 0xa1, 0x42, 0xbe, 0x2a, 0xa5, 0x68, 0x45, 0x6f, 0xc4, 0x26, 0x2e, 0xd5, 0x68, 0x9b, 0x22, - 0xb2, 0x9b, 0xcd, 0x9b, 0x95, 0x11, 0x5f, 0xac, 0x30, 0xd0, 0xa7, 0x1c, 0x18, 0x6e, 0x6a, 0x81, - 0x60, 0x91, 0xbf, 0x67, 0x23, 0x70, 0xa1, 0x51, 0xe5, 0x79, 0x36, 0x3a, 0x04, 0x1b, 0x5c, 0xd1, - 0x02, 0x9c, 0x8a, 0x49, 0xb2, 0xba, 0x13, 0x90, 0x48, 0x5d, 0xb5, 0x16, 0x77, 0xef, 0x55, 0xd2, - 0x7c, 0x39, 0x8b, 0x80, 0x3b, 0xfb, 0xe4, 0xa6, 0x3c, 0x16, 0x8f, 0x9c, 0xf2, 0x38, 0x07, 0xe3, - 0x9b, 0x9e, 0xdf, 0x68, 0x47, 0xa4, 0x6b, 0xe2, 0xe4, 0x7c, 0xa6, 0x1d, 0x77, 0xf4, 0x60, 0xf7, - 0x36, 0x1a, 0x5e, 0x2d, 0x2e, 0xf5, 0x6b, 0xf7, 0x36, 0x28, 0x00, 0x73, 0xb8, 0xfb, 0x8f, 0x1d, - 0xe0, 0x45, 0x4f, 0xa6, 0x37, 0x37, 0xfd, 0xc0, 0x4f, 0x76, 0xd1, 0xd7, 0x1c, 0x18, 0x0f, 0xc2, - 0x2a, 0x99, 0x0e, 0x12, 0x5f, 0x02, 0xed, 0x15, 0x96, 0x66, 0xbc, 0xae, 0x65, 0xc8, 0xf3, 0x1b, - 0xf4, 0x59, 0x28, 0xee, 0x18, 0x86, 0x7b, 0x1e, 0xce, 0xe6, 0x12, 0x70, 0xdf, 0xec, 0x01, 0xb3, - 0x76, 0x0b, 0x7a, 0x11, 0x8a, 0x0d, 0x56, 0x4d, 0xc0, 0xb9, 0xc7, 0xa2, 0x3c, 0x6c, 0xad, 0x78, - 0xb9, 0x01, 0x4e, 0x09, 0xcd, 0xc1, 0x10, 0x2b, 0x08, 0x23, 0x6a, 0x3d, 0xf0, 0x37, 0xc2, 0x4d, - 0xbf, 0x67, 0xa5, 0x9a, 0xee, 0x98, 0x3f, 0xb1, 0xde, 0x0d, 0xbd, 0x0e, 0xfd, 0x1b, 0xbc, 0x2c, - 0x9e, 0xbd, 0xd0, 0x95, 0xa8, 0xb3, 0xc7, 0x94, 0x19, 0x59, 0x74, 0xef, 0x4e, 0xfa, 0x2f, 0x96, - 0x1c, 0xd1, 0x2e, 0x0c, 0x78, 0xf2, 0x99, 0xf6, 0xda, 0xca, 0xc3, 0x37, 0xf6, 0x8f, 0x48, 0xb4, - 0x90, 0xcf, 0x50, 0xb1, 0xcb, 0x64, 0xa4, 0x14, 0x0f, 0x95, 0x91, 0xf2, 0x6d, 0x07, 0x20, 0xfd, - 0x24, 0x00, 0xba, 0x05, 0x03, 0xf1, 0x65, 0xc3, 0xca, 0xb7, 0x71, 0x79, 0x5a, 0x50, 0xd4, 0x2e, - 0x18, 0x0a, 0x08, 0x56, 0xdc, 0xee, 0xe6, 0x99, 0xf8, 0x99, 0x03, 0x67, 0xf2, 0x3e, 0x5d, 0xf0, - 0x00, 0x47, 0x7c, 0x54, 0xa7, 0x84, 0xe8, 0xb0, 0x16, 0x91, 0x4d, 0xff, 0x56, 0x36, 0x69, 0x65, - 0x49, 0x36, 0xe0, 0x14, 0xc7, 0xfd, 0x5e, 0x1f, 0x28, 0xc6, 0xc7, 0xe4, 0xc4, 0x78, 0x8a, 0x1a, - 0x39, 0xb5, 0xb4, 0x5c, 0xa3, 0xc2, 0xc3, 0x0c, 0x8a, 0x45, 0x2b, 0x35, 0x74, 0x64, 0x2e, 0xb5, - 0x10, 0xd9, 0x6c, 0x17, 0xca, 0x9c, 0x6b, 0xac, 0x5a, 0xf3, 0xdc, 0x22, 0xc5, 0x13, 0x71, 0x8b, - 0xf4, 0xd9, 0x77, 0x8b, 0x3c, 0x03, 0xfd, 0x51, 0xd8, 0x20, 0xd3, 0xf8, 0x9a, 0x50, 0xdf, 0xd3, - 0x42, 0xba, 0x1c, 0x8c, 0x65, 0x7b, 0xb6, 0x86, 0xe7, 0xc0, 0xe1, 0x6a, 0x78, 0xa2, 0xef, 0x39, - 0x07, 0x78, 0x5e, 0x06, 0x6d, 0x9d, 0x09, 0xb9, 0x95, 0xac, 0x98, 0x2d, 0x72, 0x2f, 0xee, 0x9c, - 0xaf, 0x3b, 0x70, 0x8a, 0x04, 0x95, 0x68, 0x97, 0xd1, 0x11, 0xd4, 0x44, 0xe8, 0xf4, 0xba, 0x8d, - 0x97, 0xef, 0x4a, 0x96, 0x38, 0x8f, 0x8b, 0x74, 0x80, 0x71, 0xe7, 0x30, 0xdc, 0x9f, 0x14, 0xe0, - 0x74, 0x0e, 0x05, 0x76, 0x4d, 0xa6, 0x49, 0x37, 0xd0, 0x62, 0x35, 0xfb, 0xfa, 0x2c, 0x09, 0x38, - 0x56, 0x18, 0x68, 0x0d, 0xce, 0x6c, 0x35, 0xe3, 0x94, 0xca, 0x6c, 0x18, 0x24, 0xe4, 0x96, 0x7c, - 0x99, 0x64, 0x14, 0xf4, 0xcc, 0x52, 0x0e, 0x0e, 0xce, 0xed, 0x49, 0xb5, 0x0d, 0x12, 0x78, 0x1b, - 0x0d, 0x92, 0x36, 0x89, 0x4b, 0x5e, 0x4a, 0xdb, 0xb8, 0x92, 0x69, 0xc7, 0x1d, 0x3d, 0xd0, 0xe7, - 0x1c, 0x78, 0x24, 0x26, 0xd1, 0x36, 0x89, 0xca, 0x7e, 0x95, 0xcc, 0xb6, 0xe3, 0x24, 0x6c, 0x92, - 0xe8, 0x1e, 0x5d, 0x83, 0x93, 0xfb, 0x7b, 0x93, 0x8f, 0x94, 0xbb, 0x53, 0xc3, 0x07, 0xb1, 0x72, - 0x3f, 0xe7, 0xc0, 0x68, 0x99, 0x19, 0xab, 0x4a, 0xf5, 0xb5, 0x5d, 0x7a, 0xf0, 0x29, 0x55, 0x52, - 0x20, 0x23, 0xc4, 0xcc, 0x22, 0x00, 0xee, 0xab, 0x30, 0x5e, 0x26, 0x4d, 0xaf, 0x55, 0x67, 0x37, - 0x34, 0x79, 0x9a, 0xce, 0x45, 0x18, 0x8c, 0x25, 0x2c, 0xfb, 0xf1, 0x10, 0x85, 0x8c, 0x53, 0x1c, - 0xf4, 0x24, 0x4f, 0x29, 0x92, 0xf7, 0x3c, 0x06, 0xb9, 0x91, 0xc0, 0xf3, 0x90, 0x62, 0x2c, 0xdb, - 0xdc, 0x1d, 0x18, 0x4e, 0xbb, 0x93, 0x4d, 0x54, 0x83, 0xb1, 0x8a, 0x76, 0x45, 0x2a, 0x4d, 0x4e, - 0x3f, 0xfc, 0x6d, 0x2a, 0x5e, 0x10, 0xd5, 0x24, 0x82, 0xb3, 0x54, 0xdd, 0x2f, 0x16, 0x60, 0x4c, - 0x71, 0x16, 0x21, 0xaf, 0x37, 0xb2, 0x69, 0x50, 0xd8, 0x46, 0xa9, 0x13, 0x73, 0x25, 0x0f, 0x48, - 0x85, 0x7a, 0x23, 0x9b, 0x0a, 0x75, 0xac, 0xec, 0x3b, 0xa2, 0x78, 0xdf, 0x2e, 0xc0, 0x80, 0x2a, - 0xbc, 0xf2, 0x22, 0x14, 0x99, 0x1d, 0x77, 0x7f, 0xda, 0x28, 0xb3, 0x09, 0x31, 0xa7, 0x44, 0x49, - 0xb2, 0x4c, 0x8e, 0x7b, 0xae, 0x3a, 0x39, 0xc8, 0xdd, 0x6f, 0x5e, 0x94, 0x60, 0x4e, 0x09, 0x2d, - 0x41, 0x0f, 0x09, 0xaa, 0x42, 0x2d, 0x3d, 0x3a, 0x41, 0xf6, 0xd1, 0x9e, 0x2b, 0x41, 0x15, 0x53, - 0x2a, 0xac, 0xf4, 0x21, 0xd7, 0x3e, 0x32, 0x9f, 0x68, 0x10, 0xaa, 0x87, 0x68, 0x75, 0x7f, 0xa5, - 0x07, 0xfa, 0xca, 0xed, 0x0d, 0xaa, 0x60, 0x7f, 0xcb, 0x81, 0xd3, 0x3b, 0x99, 0x92, 0xac, 0xe9, - 0x96, 0xbd, 0x6e, 0xcf, 0x05, 0xa9, 0x67, 0x13, 0x3d, 0x22, 0xbf, 0x3f, 0x9d, 0xd3, 0x88, 0xf3, - 0x86, 0x63, 0x54, 0x45, 0xec, 0x39, 0x96, 0xaa, 0x88, 0xb7, 0x8e, 0x39, 0x7d, 0x7d, 0xa4, 0x5b, - 0xea, 0xba, 0xfb, 0x3b, 0x45, 0x00, 0xfe, 0x34, 0x56, 0x5b, 0xc9, 0x61, 0x7c, 0x54, 0xcf, 0xc3, - 0xb0, 0xfc, 0x20, 0x7e, 0xde, 0xd7, 0x3f, 0x16, 0xb4, 0x36, 0x6c, 0x60, 0x32, 0x83, 0x20, 0x48, - 0xa2, 0x5d, 0xae, 0x34, 0x66, 0x53, 0xd4, 0x55, 0x0b, 0xd6, 0xb0, 0xd0, 0x94, 0xe1, 0xf3, 0xe7, - 0xa1, 0xdc, 0xd1, 0x03, 0x5c, 0xf4, 0xef, 0x83, 0x51, 0xb3, 0x56, 0x83, 0xd0, 0x94, 0x54, 0xe8, - 0xd5, 0x2c, 0xf1, 0x80, 0x33, 0xd8, 0x74, 0x13, 0x57, 0xa3, 0x5d, 0xdc, 0x0e, 0x84, 0xca, 0xa4, - 0x36, 0xf1, 0x1c, 0x83, 0x62, 0xd1, 0xca, 0x2e, 0xca, 0xb3, 0xd3, 0x88, 0xc3, 0xc5, 0x65, 0xfb, - 0xf4, 0xa2, 0xbc, 0xd6, 0x86, 0x0d, 0x4c, 0xca, 0x41, 0xf8, 0xf8, 0xc0, 0x7c, 0x4d, 0x32, 0x8e, - 0xb9, 0x16, 0x8c, 0x86, 0xa6, 0x6f, 0x82, 0xe7, 0x6b, 0xbd, 0xeb, 0x90, 0x5b, 0xcf, 0xe8, 0xcb, - 0x43, 0xe6, 0x19, 0x57, 0x46, 0x86, 0x3e, 0xd5, 0x19, 0xf5, 0x4c, 0xee, 0x61, 0x33, 0xd5, 0xb0, - 0x6b, 0xb2, 0xf5, 0x1a, 0x9c, 0x69, 0x85, 0xd5, 0xb5, 0xc8, 0x0f, 0x23, 0x3f, 0xd9, 0x9d, 0x6d, - 0x78, 0x71, 0xcc, 0x36, 0xc6, 0x88, 0xa9, 0x9c, 0xac, 0xe5, 0xe0, 0xe0, 0xdc, 0x9e, 0x54, 0xbb, - 0x6f, 0x09, 0x20, 0x4b, 0x33, 0x2a, 0x72, 0xed, 0x5e, 0x22, 0x62, 0xd5, 0xea, 0x9e, 0x86, 0x53, - 0xe5, 0x76, 0xab, 0xd5, 0xf0, 0x49, 0x55, 0xf9, 0xd4, 0xdd, 0xf7, 0xc3, 0x98, 0xa8, 0x99, 0xa8, - 0x54, 0x81, 0x23, 0x55, 0xf8, 0x75, 0xff, 0xc4, 0x81, 0xb1, 0x4c, 0x52, 0x07, 0x7a, 0x3d, 0x7b, - 0x80, 0x5b, 0x71, 0x58, 0xe9, 0x67, 0x37, 0x7f, 0x49, 0x73, 0x95, 0x81, 0xba, 0x4c, 0x5e, 0xb6, - 0x76, 0x07, 0x80, 0xa5, 0xf8, 0xf2, 0x13, 0x41, 0xcf, 0x80, 0x76, 0x3f, 0x5b, 0x80, 0xfc, 0x4c, - 0x1a, 0xf4, 0xb1, 0xce, 0x05, 0x78, 0xd1, 0xe2, 0x02, 0x88, 0x54, 0x9e, 0xee, 0x6b, 0x10, 0x98, - 0x6b, 0xb0, 0x62, 0x69, 0x0d, 0x04, 0xdf, 0xce, 0x95, 0xf8, 0x5f, 0x0e, 0x0c, 0xad, 0xaf, 0x2f, - 0x2b, 0xff, 0x12, 0x86, 0x73, 0x31, 0xbf, 0xe3, 0xcc, 0xe2, 0x94, 0xb3, 0x61, 0xb3, 0xc5, 0xc3, - 0x96, 0x22, 0x9c, 0xca, 0xca, 0x57, 0x96, 0x73, 0x31, 0x70, 0x97, 0x9e, 0x68, 0x11, 0x4e, 0xeb, - 0x2d, 0x65, 0xed, 0xe3, 0x5f, 0x45, 0x51, 0x57, 0xa4, 0xb3, 0x19, 0xe7, 0xf5, 0xc9, 0x92, 0x12, - 0xae, 0x42, 0xf1, 0xb1, 0xfd, 0x0e, 0x52, 0xa2, 0x19, 0xe7, 0xf5, 0x71, 0x57, 0x61, 0x68, 0xdd, - 0x8b, 0xd4, 0xc4, 0x3f, 0x00, 0xe3, 0x95, 0xb0, 0x29, 0x5d, 0x34, 0xcb, 0x64, 0x9b, 0x34, 0xc4, - 0x94, 0x79, 0x89, 0xfe, 0x4c, 0x1b, 0xee, 0xc0, 0x76, 0xff, 0xfb, 0x05, 0x50, 0x77, 0xb6, 0x0e, - 0x71, 0xc2, 0xb4, 0x54, 0x8e, 0x61, 0xd1, 0x72, 0x8e, 0xa1, 0x92, 0xb5, 0x99, 0x3c, 0xc3, 0x24, - 0xcd, 0x33, 0xec, 0xb3, 0x9d, 0x67, 0xa8, 0x14, 0xc6, 0x8e, 0x5c, 0xc3, 0xaf, 0x38, 0x30, 0x1c, - 0x84, 0x55, 0xa2, 0x82, 0x51, 0xfd, 0x4c, 0x6b, 0x7d, 0xc5, 0x5e, 0xf2, 0x34, 0xcf, 0x99, 0x13, - 0xe4, 0x79, 0x26, 0xaa, 0x3a, 0xa2, 0xf4, 0x26, 0x6c, 0x8c, 0x03, 0xcd, 0x6b, 0x4e, 0x43, 0xee, - 0x9b, 0x7f, 0x34, 0xcf, 0x7a, 0xb8, 0xab, 0x07, 0xf0, 0x96, 0xa6, 0x37, 0x0d, 0x5a, 0xff, 0x32, - 0x7d, 0x1a, 0x62, 0x90, 0x15, 0x58, 0x53, 0x7d, 0xca, 0x85, 0x3e, 0x9e, 0xb2, 0x2a, 0x2a, 0xd8, - 0xb0, 0xc8, 0x17, 0x4f, 0x67, 0xc5, 0xa2, 0x05, 0x25, 0x32, 0xe0, 0x3d, 0x64, 0xab, 0x9e, 0xba, - 0x11, 0x50, 0xcf, 0x8f, 0x78, 0xa3, 0x17, 0x74, 0xa3, 0x74, 0xf8, 0x30, 0x46, 0xe9, 0x48, 0x57, - 0x83, 0xf4, 0x0b, 0x0e, 0x0c, 0x57, 0xb4, 0xfa, 0xe6, 0xa5, 0xa7, 0x6d, 0x7d, 0x96, 0x35, 0xaf, - 0x0c, 0x3d, 0x0f, 0xa8, 0x18, 0xf5, 0xd4, 0x0d, 0xee, 0xac, 0xe4, 0x1e, 0xb3, 0xc0, 0xd9, 0xd1, - 0x6f, 0xe5, 0xa6, 0xbe, 0x69, 0xd1, 0xcb, 0x24, 0x3e, 0x0a, 0xc3, 0x82, 0x17, 0xba, 0x0d, 0x03, - 0x32, 0xeb, 0x59, 0xe4, 0x24, 0x63, 0x1b, 0x1e, 0x6e, 0x33, 0x8c, 0x26, 0x0b, 0x75, 0x71, 0x28, - 0x56, 0x1c, 0x51, 0x1d, 0x7a, 0xaa, 0x5e, 0x4d, 0x64, 0x27, 0xaf, 0xd8, 0xa9, 0x83, 0x28, 0x79, - 0x32, 0xf3, 0x6a, 0x6e, 0x7a, 0x01, 0x53, 0x16, 0xe8, 0x56, 0x5a, 0x20, 0x7a, 0xdc, 0xda, 0xe9, - 0x6b, 0xaa, 0x49, 0xdc, 0xc7, 0xd0, 0x51, 0x6f, 0xba, 0x2a, 0x22, 0x8f, 0x7f, 0x81, 0xb1, 0x9d, - 0xb7, 0x53, 0x48, 0x91, 0x57, 0x7e, 0x48, 0xa3, 0x97, 0x94, 0x0b, 0xfb, 0x1c, 0xfc, 0xcf, 0xdb, - 0xe2, 0xc2, 0xea, 0x17, 0x64, 0x3f, 0x03, 0xdf, 0x80, 0xbe, 0x16, 0xcb, 0x62, 0x28, 0xfd, 0x82, - 0xad, 0xb3, 0x85, 0x67, 0x45, 0xf0, 0xbd, 0xc9, 0xff, 0xc7, 0x82, 0x07, 0xba, 0x02, 0xfd, 0xfc, - 0x3b, 0x07, 0x3c, 0x3b, 0x7c, 0xe8, 0xd2, 0x44, 0xf7, 0xaf, 0x25, 0xa4, 0x07, 0x05, 0xff, 0x1d, - 0x63, 0xd9, 0x17, 0x7d, 0xd1, 0x81, 0x51, 0x2a, 0x51, 0xd3, 0x0f, 0x33, 0x94, 0x90, 0x2d, 0x99, - 0x75, 0x3d, 0xa6, 0x1a, 0x89, 0x94, 0x35, 0xca, 0x4c, 0x5a, 0x34, 0xd8, 0xe1, 0x0c, 0x7b, 0xf4, - 0x06, 0x0c, 0xc4, 0x7e, 0x95, 0x54, 0xbc, 0x28, 0x2e, 0x9d, 0x3e, 0x9e, 0xa1, 0xa4, 0xb1, 0x0e, - 0xc1, 0x08, 0x2b, 0x96, 0xb9, 0x9f, 0x43, 0x3f, 0xf3, 0x80, 0x3f, 0x87, 0xfe, 0xd7, 0x1d, 0x38, - 0xcb, 0xeb, 0x72, 0x67, 0x8b, 0xb2, 0x9f, 0xbd, 0x47, 0xf7, 0x0a, 0x4b, 0x6b, 0x9f, 0xce, 0x23, - 0x89, 0xf3, 0x39, 0xb1, 0xc2, 0x9e, 0xe6, 0x77, 0x34, 0xce, 0x59, 0x8d, 0xf9, 0x1d, 0xfe, 0xdb, - 0x19, 0xe8, 0x39, 0x18, 0x6a, 0x89, 0xe3, 0xd0, 0x8f, 0x9b, 0xec, 0x92, 0x42, 0x0f, 0xbf, 0xc8, - 0xb5, 0x96, 0x82, 0xb1, 0x8e, 0x63, 0x54, 0x79, 0x7d, 0xe6, 0xa0, 0x2a, 0xaf, 0xe8, 0x3a, 0x0c, - 0x25, 0x61, 0x83, 0x44, 0xc2, 0x52, 0x2d, 0xb1, 0x1d, 0x78, 0x21, 0xef, 0xdd, 0x5a, 0x57, 0x68, - 0xa9, 0x25, 0x9b, 0xc2, 0x62, 0xac, 0xd3, 0x61, 0x89, 0xa1, 0xa2, 0xde, 0x79, 0xc4, 0x4c, 0xd8, - 0x87, 0x33, 0x89, 0xa1, 0x7a, 0x23, 0x36, 0x71, 0xd1, 0x02, 0x9c, 0x6a, 0x75, 0xd8, 0xc0, 0xfc, - 0x9a, 0x92, 0x4a, 0x27, 0xe8, 0x34, 0x80, 0x3b, 0xfb, 0x18, 0xd6, 0xef, 0x23, 0x07, 0x59, 0xbf, - 0x5d, 0x6a, 0x9e, 0x3e, 0x7a, 0x2f, 0x35, 0x4f, 0x51, 0x15, 0x1e, 0xf5, 0xda, 0x49, 0xc8, 0x6a, - 0x74, 0x98, 0x5d, 0x78, 0x8e, 0xec, 0xe3, 0x3c, 0xed, 0x76, 0x7f, 0x6f, 0xf2, 0xd1, 0xe9, 0x03, - 0xf0, 0xf0, 0x81, 0x54, 0xd0, 0x6b, 0x30, 0x40, 0x44, 0xdd, 0xd6, 0xd2, 0xcf, 0xd9, 0x52, 0x12, - 0xcc, 0x4a, 0xb0, 0x32, 0xe5, 0x91, 0xc3, 0xb0, 0xe2, 0x87, 0xd6, 0x61, 0xa8, 0x1e, 0xc6, 0xc9, - 0x74, 0xc3, 0xf7, 0x62, 0x12, 0x97, 0x1e, 0x63, 0x9b, 0x26, 0x57, 0xf7, 0xba, 0x2a, 0xd1, 0xd2, - 0x3d, 0x73, 0x35, 0xed, 0x89, 0x75, 0x32, 0x88, 0xb0, 0xc8, 0x1f, 0x4b, 0x10, 0x96, 0x51, 0x99, - 0x0b, 0x6c, 0x62, 0x4f, 0xe5, 0x51, 0x5e, 0x0b, 0xab, 0x65, 0x13, 0x5b, 0x85, 0xfe, 0x74, 0x20, - 0xce, 0xd2, 0x44, 0xcf, 0xc3, 0x70, 0x2b, 0xac, 0x96, 0x5b, 0xa4, 0xb2, 0xe6, 0x25, 0x95, 0x7a, - 0x69, 0xd2, 0xf4, 0xba, 0xad, 0x69, 0x6d, 0xd8, 0xc0, 0x44, 0x2d, 0xe8, 0x6f, 0xf2, 0xcb, 0xdb, - 0xa5, 0x27, 0x6c, 0xd9, 0x36, 0xe2, 0x36, 0x38, 0xd7, 0x17, 0xc4, 0x0f, 0x2c, 0xd9, 0xa0, 0x7f, - 0xe0, 0xc0, 0x58, 0xe6, 0xda, 0x4d, 0xe9, 0x1d, 0xd6, 0x54, 0x16, 0x93, 0xf0, 0xcc, 0x53, 0x6c, - 0xf9, 0x4c, 0xe0, 0x9d, 0x4e, 0x10, 0xce, 0x8e, 0x88, 0xaf, 0x0b, 0xab, 0xc0, 0x50, 0x7a, 0xd2, - 0xde, 0xba, 0x30, 0x82, 0x72, 0x5d, 0xd8, 0x0f, 0x2c, 0xd9, 0xa0, 0x67, 0xa0, 0x5f, 0x14, 0x4b, - 0x2b, 0x3d, 0x65, 0x86, 0x6f, 0x45, 0x4d, 0x35, 0x2c, 0xdb, 0x27, 0xde, 0x0f, 0xa7, 0x3a, 0x4c, - 0xb7, 0x23, 0x95, 0x01, 0xf8, 0x0d, 0x07, 0xf4, 0x1b, 0xb3, 0xd6, 0x3f, 0x96, 0xf0, 0x3c, 0x0c, - 0x57, 0xf8, 0x27, 0xd5, 0xf8, 0x9d, 0xdb, 0x5e, 0xd3, 0xff, 0x39, 0xab, 0xb5, 0x61, 0x03, 0xd3, - 0xbd, 0x0a, 0xa8, 0xb3, 0x92, 0xf5, 0x3d, 0xd5, 0x98, 0xf9, 0x47, 0x0e, 0x8c, 0x18, 0x3a, 0x83, - 0xf5, 0x88, 0xdf, 0x3c, 0xa0, 0xa6, 0x1f, 0x45, 0x61, 0xa4, 0x7f, 0xbb, 0x4a, 0x94, 0xee, 0x65, - 0xf7, 0x9d, 0x56, 0x3a, 0x5a, 0x71, 0x4e, 0x0f, 0xf7, 0x9f, 0xf6, 0x42, 0x9a, 0xf3, 0xab, 0xca, - 0x8d, 0x3a, 0x5d, 0xcb, 0x8d, 0x3e, 0x0b, 0x03, 0xaf, 0xc6, 0x61, 0xb0, 0x96, 0x16, 0x25, 0x55, - 0xcf, 0xe2, 0x85, 0xf2, 0xea, 0x35, 0x86, 0xa9, 0x30, 0x18, 0xf6, 0x47, 0xe7, 0xfd, 0x46, 0xd2, - 0x59, 0xb5, 0xf2, 0x85, 0x17, 0x39, 0x1c, 0x2b, 0x0c, 0xf6, 0x19, 0xab, 0x6d, 0xa2, 0x1c, 0xe3, - 0xe9, 0x67, 0xac, 0x78, 0x91, 0x7a, 0xd6, 0x86, 0x2e, 0xc2, 0xa0, 0x72, 0xaa, 0x0b, 0x4f, 0xbd, - 0x5a, 0x29, 0xe5, 0x79, 0xc7, 0x29, 0x0e, 0x53, 0x08, 0x85, 0x23, 0x56, 0xb8, 0x50, 0xca, 0x36, - 0xcc, 0x93, 0x8c, 0x6b, 0x97, 0xcb, 0x76, 0x09, 0xc6, 0x8a, 0x65, 0x5e, 0xd8, 0x73, 0xf0, 0x38, - 0xc2, 0x9e, 0x7a, 0x02, 0x7a, 0xf1, 0xb0, 0x09, 0xe8, 0xe6, 0xde, 0x1e, 0x38, 0xd4, 0xde, 0xfe, - 0x74, 0x0f, 0xf4, 0xdf, 0x20, 0x11, 0x2b, 0xd6, 0xfc, 0x0c, 0xf4, 0x6f, 0xf3, 0x7f, 0xb3, 0x37, - 0x09, 0x05, 0x06, 0x96, 0xed, 0xf4, 0xb9, 0x6d, 0xb4, 0xfd, 0x46, 0x75, 0x2e, 0x7d, 0x8b, 0xd3, - 0x3a, 0x6f, 0xb2, 0x01, 0xa7, 0x38, 0xb4, 0x43, 0x8d, 0x6a, 0xf6, 0xcd, 0xa6, 0x9f, 0x64, 0x93, - 0x80, 0x16, 0x64, 0x03, 0x4e, 0x71, 0xd0, 0x53, 0xd0, 0x57, 0xf3, 0x93, 0x75, 0xaf, 0x96, 0x8d, - 0xf2, 0x2d, 0x30, 0x28, 0x16, 0xad, 0x2c, 0x4c, 0xe4, 0x27, 0xeb, 0x11, 0x61, 0x9e, 0xdd, 0x8e, - 0x92, 0x02, 0x0b, 0x5a, 0x1b, 0x36, 0x30, 0xd9, 0x90, 0x42, 0x31, 0x33, 0x91, 0x01, 0x99, 0x0e, - 0x49, 0x36, 0xe0, 0x14, 0x87, 0xee, 0xff, 0x4a, 0xd8, 0x6c, 0xf9, 0x0d, 0x91, 0x9b, 0xab, 0xed, - 0xff, 0x59, 0x01, 0xc7, 0x0a, 0x83, 0x62, 0x53, 0x11, 0x46, 0xc5, 0x4f, 0xf6, 0x93, 0x41, 0x6b, - 0x02, 0x8e, 0x15, 0x86, 0x7b, 0x03, 0x46, 0xf8, 0x9b, 0x3c, 0xdb, 0xf0, 0xfc, 0xe6, 0xc2, 0x2c, - 0xba, 0xd2, 0x91, 0x80, 0xfe, 0x4c, 0x4e, 0x02, 0xfa, 0x59, 0xa3, 0x53, 0x67, 0x22, 0xba, 0xfb, - 0xa3, 0x02, 0x0c, 0x9c, 0xe0, 0x57, 0xd7, 0x4e, 0xfc, 0x03, 0xa2, 0xe8, 0x56, 0xe6, 0x8b, 0x6b, - 0x6b, 0x36, 0xef, 0x93, 0x1c, 0xf8, 0xb5, 0xb5, 0xff, 0x5a, 0x80, 0x73, 0x12, 0x35, 0xfd, 0x80, - 0x3e, 0xfb, 0x64, 0xd0, 0xf1, 0x2f, 0x74, 0x64, 0x2c, 0xf4, 0x9a, 0x3d, 0x6b, 0x74, 0x61, 0xb6, - 0xeb, 0x52, 0xbf, 0x96, 0x59, 0x6a, 0x6c, 0x95, 0xeb, 0xc1, 0x8b, 0xfd, 0xa7, 0x0e, 0x4c, 0xe4, - 0x2f, 0xf6, 0x09, 0x7c, 0xe4, 0xee, 0x0d, 0xf3, 0x23, 0x77, 0xbf, 0x64, 0x6f, 0x8b, 0x99, 0x53, - 0xe9, 0xf2, 0xb9, 0xbb, 0x3f, 0x76, 0xe0, 0x8c, 0xec, 0xc0, 0x4e, 0xcf, 0x19, 0x3f, 0x60, 0x89, - 0x28, 0xc7, 0xbf, 0xcd, 0x6e, 0x1b, 0xdb, 0xec, 0x65, 0x7b, 0x13, 0xd7, 0xe7, 0xd1, 0xf5, 0xe3, - 0xc0, 0x7f, 0xe4, 0x40, 0x29, 0xaf, 0xc3, 0x09, 0x3c, 0xf2, 0xd7, 0xcd, 0x47, 0x7e, 0xe3, 0x78, - 0x66, 0xde, 0xfd, 0x81, 0x97, 0xba, 0x2d, 0x14, 0x6a, 0x48, 0xbd, 0xca, 0xb1, 0x15, 0xa3, 0xe5, - 0x2c, 0xf2, 0x15, 0xb4, 0x06, 0xf4, 0xc5, 0x2c, 0x6b, 0x43, 0x6c, 0x81, 0xab, 0x36, 0xb4, 0x2d, - 0x4a, 0x4f, 0xf8, 0xd8, 0xd9, 0xff, 0x58, 0xf0, 0x70, 0xff, 0xd0, 0x81, 0xe1, 0x13, 0xfc, 0x78, - 0x65, 0x68, 0x3e, 0xe4, 0x17, 0xec, 0x3d, 0xe4, 0x2e, 0x0f, 0x76, 0xaf, 0x08, 0x1d, 0xdf, 0xf3, - 0x43, 0x9f, 0x71, 0x54, 0xa6, 0x06, 0xcf, 0x66, 0xfb, 0x90, 0xbd, 0x71, 0x1c, 0xa5, 0x9a, 0x1c, - 0xfa, 0x7a, 0xa6, 0xc4, 0x5e, 0xc1, 0x56, 0xdd, 0x9a, 0x8e, 0xd1, 0xdc, 0x43, 0xa9, 0xbd, 0xaf, - 0x38, 0x00, 0x7c, 0x9c, 0xa2, 0x42, 0x2f, 0x1d, 0xdb, 0xc6, 0xb1, 0xad, 0x14, 0x65, 0xc2, 0x87, - 0xa6, 0x04, 0x64, 0xda, 0x80, 0xb5, 0x91, 0xdc, 0x47, 0x0d, 0xbd, 0xfb, 0x2e, 0xdf, 0xf7, 0x45, - 0x07, 0xc6, 0x32, 0xc3, 0xcd, 0xe9, 0xbf, 0x69, 0x7e, 0xe7, 0xcb, 0x82, 0xae, 0x60, 0xd6, 0x6d, - 0xd5, 0xdd, 0x01, 0x7b, 0x2e, 0x18, 0x1f, 0x42, 0x45, 0xaf, 0xc3, 0xa0, 0xb4, 0xe5, 0xe5, 0xf6, - 0xb6, 0xf9, 0xbd, 0x43, 0xa5, 0xb0, 0x4b, 0x48, 0x8c, 0x53, 0x7e, 0x99, 0x44, 0xb0, 0xc2, 0xa1, - 0x12, 0xc1, 0x1e, 0xec, 0xd7, 0x12, 0xf3, 0x3d, 0xad, 0xbd, 0xc7, 0xe2, 0x69, 0x7d, 0xd4, 0xba, - 0xa7, 0xf5, 0xb1, 0x13, 0xf6, 0xb4, 0x6a, 0x61, 0xaf, 0xe2, 0x7d, 0x84, 0xbd, 0x5e, 0x87, 0x33, - 0xdb, 0xa9, 0x19, 0xa5, 0x76, 0x92, 0xa8, 0xd1, 0xf2, 0x4c, 0xae, 0x7f, 0x95, 0x9a, 0x84, 0x71, - 0x42, 0x82, 0x44, 0x33, 0xc0, 0xd2, 0x1c, 0xb4, 0x1b, 0x39, 0xe4, 0x70, 0x2e, 0x93, 0x6c, 0xfc, - 0xa2, 0xff, 0x10, 0xf1, 0x8b, 0xef, 0x38, 0x70, 0xd6, 0xeb, 0xb8, 0x12, 0x84, 0xc9, 0xa6, 0x48, - 0xa2, 0xb8, 0x69, 0x4f, 0x2f, 0x37, 0xc8, 0x8b, 0x40, 0x51, 0x5e, 0x13, 0xce, 0x1f, 0x10, 0x7a, - 0x32, 0x0d, 0x26, 0xf3, 0xcc, 0xc5, 0xfc, 0xc8, 0xef, 0xd7, 0xb3, 0x19, 0x2a, 0xc0, 0x96, 0xfe, - 0x23, 0x76, 0xed, 0x47, 0x0b, 0x59, 0x2a, 0x43, 0xf7, 0x91, 0xa5, 0x92, 0x09, 0x26, 0x0d, 0x5b, - 0x0a, 0x26, 0x05, 0x30, 0xee, 0x37, 0xbd, 0x1a, 0x59, 0x6b, 0x37, 0x1a, 0xfc, 0x8e, 0x82, 0xfc, - 0x22, 0x65, 0xae, 0x4f, 0x6a, 0x39, 0xac, 0x78, 0x8d, 0xec, 0x87, 0x7f, 0xd5, 0x5d, 0x8c, 0xc5, - 0x0c, 0x25, 0xdc, 0x41, 0x9b, 0x6e, 0x58, 0x56, 0x2c, 0x8c, 0x24, 0x74, 0xb5, 0x59, 0x2a, 0xc4, - 0x00, 0xdf, 0xb0, 0x57, 0x53, 0x30, 0xd6, 0x71, 0xd0, 0x12, 0x0c, 0x56, 0x83, 0x58, 0xdc, 0x6e, - 0x1c, 0x63, 0xc2, 0xec, 0x9d, 0x54, 0x04, 0xce, 0x5d, 0x2b, 0xab, 0x7b, 0x8d, 0x8f, 0xe6, 0xd4, - 0xa1, 0x53, 0xed, 0x38, 0xed, 0x8f, 0x56, 0x18, 0x31, 0xf1, 0xc9, 0x1f, 0x9e, 0xa1, 0xf0, 0x78, - 0x97, 0x10, 0xc8, 0xdc, 0x35, 0xf9, 0xd1, 0xa2, 0x11, 0xc1, 0x4e, 0x7c, 0xbb, 0x27, 0xa5, 0xa0, - 0x7d, 0x19, 0xf4, 0xd4, 0x81, 0x5f, 0x06, 0x65, 0x05, 0x28, 0x93, 0x86, 0x0a, 0x78, 0x5e, 0xb0, - 0x56, 0x80, 0x32, 0xcd, 0xfd, 0x13, 0x05, 0x28, 0x53, 0x00, 0xd6, 0x59, 0xa2, 0xd5, 0x6e, 0x81, - 0xdf, 0xd3, 0x4c, 0x68, 0x1c, 0x3d, 0x8c, 0xab, 0x47, 0x00, 0xcf, 0x1c, 0x18, 0x01, 0xec, 0x88, - 0x58, 0x9e, 0x3d, 0x42, 0xc4, 0xb2, 0xce, 0x4a, 0x03, 0x2e, 0xcc, 0x8a, 0x20, 0xb1, 0x05, 0x8b, - 0x85, 0x95, 0x5d, 0xe0, 0xb9, 0x94, 0xec, 0x5f, 0xcc, 0x19, 0x74, 0x4d, 0x11, 0x3e, 0x7f, 0xcf, - 0x29, 0xc2, 0x54, 0x3c, 0xa7, 0x70, 0x56, 0x63, 0xb2, 0x28, 0xc4, 0x73, 0x0a, 0xc6, 0x3a, 0x4e, - 0x36, 0xfe, 0xf7, 0xf0, 0xb1, 0xc5, 0xff, 0x26, 0x4e, 0x20, 0xfe, 0xf7, 0xc8, 0xa1, 0xe3, 0x7f, - 0xb7, 0xe0, 0x74, 0x2b, 0xac, 0xce, 0xf9, 0x71, 0xd4, 0x66, 0x97, 0xb6, 0x66, 0xda, 0xd5, 0x1a, - 0x49, 0x58, 0x00, 0x71, 0xe8, 0xd2, 0x3b, 0xf5, 0x41, 0xb6, 0xd8, 0x8b, 0x2c, 0xdf, 0xd1, 0x4c, - 0x07, 0xe6, 0x0c, 0x60, 0x79, 0xa4, 0x39, 0x8d, 0x38, 0x8f, 0x85, 0x1e, 0x79, 0x7c, 0xfc, 0x64, - 0x22, 0x8f, 0x1f, 0x80, 0x81, 0xb8, 0xde, 0x4e, 0xaa, 0xe1, 0x4e, 0xc0, 0xc2, 0xcb, 0x83, 0x33, - 0xef, 0x50, 0xce, 0x59, 0x01, 0xbf, 0xb3, 0x37, 0x39, 0x2e, 0xff, 0xd7, 0xfc, 0xb2, 0x02, 0x82, - 0xbe, 0xd1, 0xe5, 0x46, 0x8a, 0x7b, 0x9c, 0x37, 0x52, 0xce, 0x1f, 0xe9, 0x36, 0x4a, 0x5e, 0x78, - 0xf5, 0x89, 0xb7, 0x5d, 0x78, 0xf5, 0x6b, 0x0e, 0x8c, 0x6c, 0xeb, 0x4e, 0x70, 0x11, 0x02, 0xb6, - 0x90, 0x8a, 0x62, 0xf8, 0xd6, 0x67, 0x5c, 0x2a, 0xe7, 0x0c, 0xd0, 0x9d, 0x2c, 0x00, 0x9b, 0x23, - 0xc9, 0x49, 0x93, 0x79, 0xf2, 0x41, 0xa5, 0xc9, 0xbc, 0xc1, 0xe4, 0x98, 0x34, 0x72, 0x59, 0x5c, - 0xd8, 0x6e, 0x96, 0xac, 0x94, 0x89, 0x2a, 0x49, 0x56, 0xe7, 0x87, 0xbe, 0xe0, 0xc0, 0xb8, 0xb4, - 0xcb, 0x44, 0x10, 0x2b, 0x16, 0x79, 0x7e, 0x36, 0xcd, 0x41, 0x96, 0x28, 0xbe, 0x9e, 0xe1, 0x83, - 0x3b, 0x38, 0x53, 0xa9, 0xae, 0xd2, 0xaa, 0x6a, 0x31, 0x4b, 0x67, 0x15, 0x3a, 0xcc, 0x74, 0x0a, - 0xc6, 0x3a, 0x0e, 0xfa, 0xa6, 0xfa, 0xdc, 0xf7, 0x33, 0x4c, 0xa0, 0xbf, 0x64, 0x59, 0x37, 0xb5, - 0xf1, 0xcd, 0x6f, 0xf4, 0x25, 0x07, 0xc6, 0x77, 0x32, 0x0e, 0x0d, 0x91, 0xe8, 0x88, 0xed, 0xbb, - 0x4a, 0xf8, 0x72, 0x67, 0xa1, 0xb8, 0x63, 0x04, 0xe8, 0x36, 0x80, 0xa7, 0x1c, 0xdd, 0x22, 0x21, - 0x72, 0xd9, 0x66, 0xf0, 0x80, 0x5f, 0xd5, 0x4a, 0x7f, 0x63, 0x8d, 0xdf, 0x7d, 0xe7, 0x38, 0xbc, - 0xad, 0xbe, 0xa4, 0xfe, 0x5f, 0x4e, 0xc3, 0xa8, 0x19, 0x9f, 0x42, 0xef, 0x32, 0xeb, 0xe1, 0x5f, - 0xc8, 0x96, 0x16, 0x1f, 0x91, 0xf8, 0x46, 0x79, 0x71, 0xa3, 0xfe, 0x77, 0xe1, 0x58, 0xeb, 0x7f, - 0xf7, 0x9c, 0x4c, 0xfd, 0xef, 0xf1, 0xe3, 0xa8, 0xff, 0x7d, 0xea, 0x48, 0xf5, 0xbf, 0xb5, 0xfa, - 0xeb, 0xbd, 0x77, 0xa9, 0xbf, 0x3e, 0x0d, 0x63, 0xf2, 0xfe, 0x0a, 0x11, 0x85, 0x9d, 0x79, 0xe8, - 0xfa, 0xbc, 0xe8, 0x32, 0x36, 0x6b, 0x36, 0xe3, 0x2c, 0x3e, 0xfa, 0xbc, 0x03, 0xc5, 0x80, 0xf5, - 0xec, 0xb3, 0xf5, 0x31, 0x14, 0x73, 0x6b, 0x31, 0x83, 0x59, 0x08, 0x25, 0x99, 0xb1, 0x5b, 0x64, - 0xb0, 0x3b, 0xf2, 0x1f, 0xcc, 0x47, 0x80, 0x5e, 0x81, 0x52, 0xb8, 0xb9, 0xd9, 0x08, 0xbd, 0x6a, - 0x5a, 0xa4, 0x5c, 0xc6, 0xd6, 0xf9, 0xfd, 0x43, 0x55, 0x49, 0x73, 0xb5, 0x0b, 0x1e, 0xee, 0x4a, - 0x01, 0x7d, 0x87, 0xaa, 0x22, 0x49, 0x18, 0x91, 0x6a, 0xea, 0x9d, 0x19, 0x64, 0x73, 0x26, 0xd6, - 0xe7, 0x5c, 0x36, 0xf9, 0xf0, 0xd9, 0xab, 0x87, 0x92, 0x69, 0xc5, 0xd9, 0x61, 0xa1, 0x08, 0xce, - 0xb5, 0xf2, 0x9c, 0x43, 0xb1, 0xb8, 0x75, 0x73, 0x90, 0x8b, 0x4a, 0xbe, 0xba, 0xe7, 0x72, 0xdd, - 0x4b, 0x31, 0xee, 0x42, 0x59, 0x2f, 0x5f, 0x3e, 0x70, 0x32, 0xe5, 0xcb, 0x3f, 0x0e, 0x50, 0x91, - 0xb5, 0xa0, 0xa4, 0xbb, 0x61, 0xc9, 0xca, 0x75, 0x10, 0x4e, 0x53, 0xfb, 0x56, 0xa2, 0x62, 0x83, - 0x35, 0x96, 0xe8, 0xff, 0xe4, 0x56, 0xda, 0xe7, 0x3e, 0x95, 0x9a, 0xf5, 0x3d, 0xf1, 0xb6, 0xab, - 0xb6, 0xff, 0x0f, 0x1d, 0x98, 0xe0, 0x3b, 0x2f, 0xab, 0xce, 0x53, 0x65, 0x42, 0xdc, 0x4f, 0xb1, - 0x9d, 0x7e, 0xc1, 0x32, 0xd1, 0xca, 0x06, 0x57, 0x16, 0xac, 0x3d, 0x60, 0x24, 0xe8, 0x2b, 0x39, - 0x46, 0xc4, 0x98, 0x2d, 0x2f, 0x65, 0x7e, 0x95, 0xf6, 0xd3, 0xfb, 0x87, 0xb1, 0x1b, 0xfe, 0x49, - 0x57, 0x27, 0x2a, 0x62, 0xc3, 0xfb, 0x6b, 0xc7, 0xe4, 0x44, 0xd5, 0x4b, 0xc9, 0x1f, 0xc9, 0x95, - 0xfa, 0x45, 0x07, 0xc6, 0xbd, 0x4c, 0xba, 0x04, 0xf3, 0xfc, 0x58, 0xf1, 0x42, 0x4d, 0x47, 0x69, - 0x0e, 0x06, 0x53, 0xeb, 0xb2, 0x99, 0x19, 0xb8, 0x83, 0xf9, 0xc4, 0x67, 0x1c, 0xfe, 0xfd, 0x99, - 0xae, 0x7a, 0xd1, 0x86, 0xa9, 0x17, 0x2d, 0xdb, 0xfc, 0x02, 0x86, 0xae, 0xa0, 0xfd, 0xaa, 0x03, - 0x67, 0xf2, 0xc4, 0x76, 0xce, 0x90, 0x3e, 0x62, 0x0e, 0xc9, 0xa2, 0xf1, 0xa1, 0x0f, 0xc8, 0x4e, - 0xd9, 0xff, 0x3f, 0x1a, 0xd4, 0x82, 0x69, 0x09, 0x69, 0x59, 0x4f, 0xae, 0x0d, 0xa0, 0xcf, 0x0f, - 0x1a, 0x7e, 0x40, 0xc4, 0x45, 0x3a, 0x9b, 0xa6, 0x98, 0xf8, 0xcc, 0x06, 0xa5, 0x8e, 0x05, 0x97, - 0x07, 0x1c, 0x5b, 0xcb, 0x7e, 0x42, 0xa8, 0xf7, 0xe4, 0x3f, 0x21, 0xb4, 0x03, 0x83, 0x3b, 0x7e, - 0x52, 0x67, 0x39, 0x01, 0x22, 0x64, 0x65, 0xe1, 0x02, 0x1a, 0x25, 0x97, 0xce, 0xfd, 0xa6, 0x64, - 0x80, 0x53, 0x5e, 0xe8, 0x22, 0x67, 0xcc, 0x52, 0x6a, 0xb3, 0xb9, 0x8e, 0x37, 0x65, 0x03, 0x4e, - 0x71, 0xe8, 0x62, 0x0d, 0xd3, 0x5f, 0xb2, 0xd0, 0x8c, 0x28, 0x46, 0x6a, 0xa3, 0xc8, 0x9c, 0xa0, - 0xc8, 0xaf, 0x79, 0xde, 0xd4, 0x78, 0x60, 0x83, 0xa3, 0xaa, 0x07, 0x3b, 0xd0, 0xb5, 0x1e, 0xec, - 0x6d, 0xa6, 0x85, 0x24, 0x7e, 0xd0, 0x26, 0xab, 0x81, 0x48, 0xc4, 0x5d, 0xb6, 0x73, 0x29, 0x95, - 0xd3, 0xe4, 0x76, 0x65, 0xfa, 0x1b, 0x6b, 0xfc, 0xb4, 0xc8, 0xc1, 0xd0, 0x81, 0x91, 0x83, 0xd4, - 0x73, 0x30, 0x6c, 0xdd, 0x73, 0x90, 0x90, 0x96, 0x15, 0xcf, 0xc1, 0xdb, 0xca, 0xc6, 0xfd, 0x53, - 0x07, 0x90, 0x52, 0x26, 0xbc, 0x78, 0x4b, 0x7c, 0xf7, 0xed, 0xf8, 0xb3, 0xdd, 0x3e, 0xe1, 0x00, - 0x04, 0xea, 0x43, 0x73, 0x76, 0x4f, 0x2d, 0x4e, 0x33, 0x1d, 0x40, 0x0a, 0xc3, 0x1a, 0x4f, 0xf7, - 0x7f, 0x38, 0x69, 0x52, 0x69, 0x3a, 0xf7, 0x13, 0xc8, 0x85, 0xda, 0x35, 0x73, 0xa1, 0xd6, 0x2d, - 0x7a, 0xa0, 0xd5, 0x34, 0xba, 0x64, 0x45, 0xfd, 0xb4, 0x00, 0x63, 0x3a, 0x72, 0x99, 0x9c, 0xc4, - 0xc3, 0xde, 0x31, 0x52, 0x1b, 0xaf, 0xdb, 0x9d, 0x6f, 0x59, 0x04, 0x32, 0xf2, 0xd2, 0x68, 0x3f, - 0x9e, 0x49, 0xa3, 0xbd, 0x69, 0x9f, 0xf5, 0xc1, 0xb9, 0xb4, 0xff, 0xcd, 0x81, 0xd3, 0x99, 0x1e, - 0x27, 0xb0, 0xc1, 0xb6, 0xcd, 0x0d, 0xf6, 0xa2, 0xf5, 0x59, 0x77, 0xd9, 0x5d, 0xdf, 0x2a, 0x74, - 0xcc, 0x96, 0x59, 0x26, 0x9f, 0x76, 0xa0, 0x98, 0x78, 0xf1, 0x96, 0x4c, 0x4b, 0xfa, 0xc8, 0xb1, - 0xec, 0x80, 0x29, 0xfa, 0xbf, 0x90, 0xce, 0x6a, 0x7c, 0x0c, 0x86, 0x39, 0xf7, 0x89, 0x4f, 0x39, - 0x00, 0x29, 0xd2, 0x83, 0x52, 0x59, 0xdd, 0xef, 0x16, 0xe0, 0x6c, 0xee, 0x36, 0x42, 0x9f, 0x55, - 0x6e, 0x26, 0xc7, 0x76, 0xd2, 0x9d, 0xc1, 0x48, 0xf7, 0x36, 0x8d, 0x18, 0xde, 0x26, 0xe1, 0x64, - 0x7a, 0x50, 0x06, 0x87, 0x10, 0xd3, 0xda, 0x62, 0xfd, 0xc4, 0x49, 0xf3, 0x38, 0x55, 0xc1, 0x99, - 0x3f, 0x83, 0xb7, 0x2b, 0xdc, 0x9f, 0x6a, 0xa9, 0xe7, 0x72, 0xa2, 0x27, 0x20, 0x2b, 0x76, 0x4c, - 0x59, 0x81, 0xed, 0x87, 0x43, 0xbb, 0x08, 0x8b, 0x8f, 0x42, 0x5e, 0x7c, 0xf4, 0x70, 0xd5, 0xea, - 0x8c, 0x7b, 0x8a, 0x85, 0x43, 0xdf, 0x53, 0x1c, 0x81, 0xa1, 0x97, 0xfd, 0x96, 0x0a, 0xe5, 0x4d, - 0x7d, 0xff, 0xc7, 0x17, 0x1e, 0xfa, 0xc1, 0x8f, 0x2f, 0x3c, 0xf4, 0xa3, 0x1f, 0x5f, 0x78, 0xe8, - 0x13, 0xfb, 0x17, 0x9c, 0xef, 0xef, 0x5f, 0x70, 0x7e, 0xb0, 0x7f, 0xc1, 0xf9, 0xd1, 0xfe, 0x05, - 0xe7, 0x3f, 0xec, 0x5f, 0x70, 0xfe, 0xd6, 0x7f, 0xbc, 0xf0, 0xd0, 0xcb, 0x03, 0x72, 0x62, 0xff, - 0x3f, 0x00, 0x00, 0xff, 0xff, 0xb3, 0xba, 0x03, 0x3b, 0x06, 0xd0, 0x00, 0x00, + // 10647 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0xbd, 0x7b, 0x70, 0x24, 0xc7, + 0x79, 0x18, 0xce, 0x59, 0x60, 0xf1, 0xf8, 0xf0, 0xbc, 0xbe, 0xd7, 0x12, 0x24, 0x0f, 0xf4, 0x50, + 0xe4, 0x8f, 0xb4, 0x29, 0x9c, 0x79, 0x27, 0xfd, 0xc2, 0x48, 0x89, 0x24, 0x3c, 0x0e, 0x38, 0x10, + 0xc0, 0x01, 0xec, 0xc5, 0xdd, 0x99, 0x14, 0x23, 0x69, 0xb0, 0xdb, 0xd8, 0x1d, 0x62, 0x77, 0x66, + 0x35, 0x33, 0x0b, 0x1c, 0xc8, 0xa3, 0xa4, 0xc8, 0x7a, 0xc6, 0x8a, 0x95, 0xd8, 0x92, 0x2c, 0x29, + 0x49, 0x95, 0xa2, 0x48, 0x89, 0x4a, 0x71, 0x92, 0x92, 0x2b, 0x7f, 0xa4, 0xec, 0xff, 0x52, 0x29, + 0x97, 0x52, 0x4e, 0x55, 0xe4, 0x32, 0x13, 0xe9, 0x8f, 0x18, 0x8c, 0x90, 0x44, 0x55, 0x49, 0x4a, + 0x55, 0x89, 0x2a, 0x76, 0xec, 0xcb, 0xa3, 0x52, 0xfd, 0x9c, 0xee, 0xd9, 0x59, 0x1c, 0x70, 0xd7, + 0xc0, 0xb1, 0xec, 0xbf, 0x80, 0xfd, 0xfa, 0xeb, 0xef, 0xeb, 0xee, 0xe9, 0xf9, 0xfa, 0x7b, 0xf5, + 0x37, 0xb0, 0x56, 0xf3, 0x93, 0x7a, 0x7b, 0x63, 0xaa, 0x12, 0x36, 0x2f, 0x7a, 0x51, 0x2d, 0x6c, + 0x45, 0xe1, 0xab, 0xec, 0x9f, 0x77, 0xee, 0x84, 0xd1, 0xd6, 0x66, 0x23, 0xdc, 0x89, 0x2f, 0x6e, + 0x5f, 0xbe, 0xd8, 0xda, 0xaa, 0x5d, 0xf4, 0x5a, 0x7e, 0x7c, 0x51, 0x42, 0x2f, 0x6e, 0x3f, 0xe7, + 0x35, 0x5a, 0x75, 0xef, 0xb9, 0x8b, 0x35, 0x12, 0x90, 0xc8, 0x4b, 0x48, 0x75, 0xaa, 0x15, 0x85, + 0x49, 0x88, 0x3e, 0x90, 0x52, 0x9c, 0x92, 0x14, 0xd9, 0x3f, 0x1f, 0x56, 0x14, 0xa7, 0xb6, 0x2f, + 0x4f, 0xb5, 0xb6, 0x6a, 0x53, 0x94, 0xe2, 0x94, 0x84, 0x4e, 0x49, 0x8a, 0x13, 0xef, 0xd4, 0xc6, + 0x54, 0x0b, 0x6b, 0xe1, 0x45, 0x46, 0x78, 0xa3, 0xbd, 0xc9, 0x7e, 0xb1, 0x1f, 0xec, 0x3f, 0xce, + 0x70, 0xc2, 0xdd, 0x7a, 0x3e, 0x9e, 0xf2, 0x43, 0x3a, 0xbe, 0x8b, 0x95, 0x30, 0x22, 0x17, 0xb7, + 0x3b, 0x06, 0x35, 0xf1, 0x0e, 0x0d, 0xa7, 0x15, 0x36, 0xfc, 0xca, 0x6e, 0x1e, 0xd6, 0xbb, 0x52, + 0xac, 0xa6, 0x57, 0xa9, 0xfb, 0x01, 0x89, 0x76, 0xd3, 0xa9, 0x37, 0x49, 0xe2, 0xe5, 0xf5, 0xba, + 0xd8, 0xad, 0x57, 0xd4, 0x0e, 0x12, 0xbf, 0x49, 0x3a, 0x3a, 0xfc, 0xff, 0x77, 0xeb, 0x10, 0x57, + 0xea, 0xa4, 0xe9, 0x75, 0xf4, 0xbb, 0xdc, 0xad, 0x5f, 0x3b, 0xf1, 0x1b, 0x17, 0xfd, 0x20, 0x89, + 0x93, 0x28, 0xdb, 0xc9, 0xbd, 0x02, 0x7d, 0xd3, 0xcd, 0xb0, 0x1d, 0x24, 0xe8, 0xbd, 0x50, 0xdc, + 0xf6, 0x1a, 0x6d, 0x52, 0x72, 0x1e, 0x77, 0x9e, 0x1e, 0x9c, 0x79, 0xf2, 0xfb, 0x7b, 0x93, 0x0f, + 0xed, 0xef, 0x4d, 0x16, 0x6f, 0x50, 0xe0, 0x9d, 0xbd, 0xc9, 0x33, 0x24, 0xa8, 0x84, 0x55, 0x3f, + 0xa8, 0x5d, 0x7c, 0x35, 0x0e, 0x83, 0xa9, 0x6b, 0xed, 0xe6, 0x06, 0x89, 0x30, 0xef, 0xe3, 0xfe, + 0x41, 0x01, 0xc6, 0xa6, 0xa3, 0x4a, 0xdd, 0xdf, 0x26, 0xe5, 0x84, 0xd2, 0xaf, 0xed, 0xa2, 0x3a, + 0xf4, 0x24, 0x5e, 0xc4, 0xc8, 0x0d, 0x5d, 0x5a, 0x99, 0xba, 0xdf, 0xe7, 0x3e, 0xb5, 0xee, 0x45, + 0x92, 0xf6, 0x4c, 0xff, 0xfe, 0xde, 0x64, 0xcf, 0xba, 0x17, 0x61, 0xca, 0x02, 0x35, 0xa0, 0x37, + 0x08, 0x03, 0x52, 0x2a, 0x30, 0x56, 0xd7, 0xee, 0x9f, 0xd5, 0xb5, 0x30, 0x50, 0xf3, 0x98, 0x19, + 0xd8, 0xdf, 0x9b, 0xec, 0xa5, 0x10, 0xcc, 0xb8, 0xd0, 0x79, 0xbd, 0xe6, 0xb7, 0x4a, 0x3d, 0xb6, + 0xe6, 0xf5, 0xb2, 0xdf, 0x32, 0xe7, 0xf5, 0xb2, 0xdf, 0xc2, 0x94, 0x85, 0xfb, 0xf9, 0x02, 0x0c, + 0x4e, 0x47, 0xb5, 0x76, 0x93, 0x04, 0x49, 0x8c, 0x3e, 0x0e, 0xd0, 0xf2, 0x22, 0xaf, 0x49, 0x12, + 0x12, 0xc5, 0x25, 0xe7, 0xf1, 0x9e, 0xa7, 0x87, 0x2e, 0x2d, 0xdd, 0x3f, 0xfb, 0x35, 0x49, 0x73, + 0x06, 0x89, 0x47, 0x0e, 0x0a, 0x14, 0x63, 0x8d, 0x25, 0x7a, 0x1d, 0x06, 0xbd, 0x28, 0xf1, 0x37, + 0xbd, 0x4a, 0x12, 0x97, 0x0a, 0x8c, 0xff, 0x0b, 0xf7, 0xcf, 0x7f, 0x5a, 0x90, 0x9c, 0x39, 0x25, + 0xd8, 0x0f, 0x4a, 0x48, 0x8c, 0x53, 0x7e, 0xee, 0x6f, 0xf7, 0xc2, 0xd0, 0x74, 0x94, 0x2c, 0xcc, + 0x96, 0x13, 0x2f, 0x69, 0xc7, 0xe8, 0xf7, 0x1c, 0x38, 0x1d, 0xf3, 0x65, 0xf3, 0x49, 0xbc, 0x16, + 0x85, 0x15, 0x12, 0xc7, 0xa4, 0x2a, 0xd6, 0x65, 0xd3, 0xca, 0xb8, 0x24, 0xb3, 0xa9, 0x72, 0x27, + 0xa3, 0x2b, 0x41, 0x12, 0xed, 0xce, 0x3c, 0x27, 0xc6, 0x7c, 0x3a, 0x07, 0xe3, 0x93, 0x6f, 0x4d, + 0x22, 0x39, 0x15, 0x4a, 0x89, 0x3f, 0x62, 0x9c, 0x37, 0x6a, 0xf4, 0x35, 0x07, 0x86, 0x5b, 0x61, + 0x35, 0xc6, 0xa4, 0x12, 0xb6, 0x5b, 0xa4, 0x2a, 0x96, 0xf7, 0xc3, 0x76, 0xa7, 0xb1, 0xa6, 0x71, + 0xe0, 0xe3, 0x3f, 0x23, 0xc6, 0x3f, 0xac, 0x37, 0x61, 0x63, 0x28, 0xe8, 0x79, 0x18, 0x0e, 0xc2, + 0xa4, 0xdc, 0x22, 0x15, 0x7f, 0xd3, 0x27, 0x55, 0xb6, 0xf1, 0x07, 0xd2, 0x9e, 0xd7, 0xb4, 0x36, + 0x6c, 0x60, 0x4e, 0xcc, 0x43, 0xa9, 0xdb, 0xca, 0xa1, 0x71, 0xe8, 0xd9, 0x22, 0xbb, 0x5c, 0xd8, + 0x60, 0xfa, 0x2f, 0x3a, 0x23, 0x05, 0x10, 0x7d, 0x8d, 0x07, 0x84, 0x64, 0x79, 0x4f, 0xe1, 0x79, + 0x67, 0xe2, 0xfd, 0x70, 0xaa, 0x63, 0xe8, 0x47, 0x21, 0xe0, 0xfe, 0xa0, 0x0f, 0x06, 0xe4, 0xa3, + 0x40, 0x8f, 0x43, 0x6f, 0xe0, 0x35, 0xa5, 0x9c, 0x1b, 0x16, 0xf3, 0xe8, 0xbd, 0xe6, 0x35, 0xe9, + 0x1b, 0xee, 0x35, 0x09, 0xc5, 0x68, 0x79, 0x49, 0x9d, 0xd1, 0xd1, 0x30, 0xd6, 0xbc, 0xa4, 0x8e, + 0x59, 0x0b, 0x7a, 0x14, 0x7a, 0x9b, 0x61, 0x95, 0xb0, 0xb5, 0x28, 0x72, 0x09, 0xb1, 0x12, 0x56, + 0x09, 0x66, 0x50, 0xda, 0x7f, 0x33, 0x0a, 0x9b, 0xa5, 0x5e, 0xb3, 0xff, 0x7c, 0x14, 0x36, 0x31, + 0x6b, 0x41, 0x5f, 0x75, 0x60, 0x5c, 0xee, 0xed, 0xe5, 0xb0, 0xe2, 0x25, 0x7e, 0x18, 0x94, 0x8a, + 0x4c, 0xa2, 0x60, 0x7b, 0xaf, 0x94, 0xa4, 0x3c, 0x53, 0x12, 0x43, 0x18, 0xcf, 0xb6, 0xe0, 0x8e, + 0x51, 0xa0, 0x4b, 0x00, 0xb5, 0x46, 0xb8, 0xe1, 0x35, 0xe8, 0x82, 0x94, 0xfa, 0xd8, 0x14, 0x94, + 0x64, 0x58, 0x50, 0x2d, 0x58, 0xc3, 0x42, 0xb7, 0xa0, 0xdf, 0xe3, 0xd2, 0xbf, 0xd4, 0xcf, 0x26, + 0xf1, 0xa2, 0x8d, 0x49, 0x18, 0xc7, 0xc9, 0xcc, 0xd0, 0xfe, 0xde, 0x64, 0xbf, 0x00, 0x62, 0xc9, + 0x0e, 0x3d, 0x0b, 0x03, 0x61, 0x8b, 0x8e, 0xdb, 0x6b, 0x94, 0x06, 0xd8, 0xc6, 0x1c, 0x17, 0x63, + 0x1d, 0x58, 0x15, 0x70, 0xac, 0x30, 0xd0, 0x33, 0xd0, 0x1f, 0xb7, 0x37, 0xe8, 0x73, 0x2c, 0x0d, + 0xb2, 0x89, 0x8d, 0x09, 0xe4, 0xfe, 0x32, 0x07, 0x63, 0xd9, 0x8e, 0xde, 0x0d, 0x43, 0x11, 0xa9, + 0xb4, 0xa3, 0x98, 0xd0, 0x07, 0x5b, 0x02, 0x46, 0xfb, 0xb4, 0x40, 0x1f, 0xc2, 0x69, 0x13, 0xd6, + 0xf1, 0xd0, 0xfb, 0x60, 0x94, 0x3e, 0xe0, 0x2b, 0xb7, 0x5a, 0x11, 0x89, 0x63, 0xfa, 0x54, 0x87, + 0x18, 0xa3, 0x73, 0xa2, 0xe7, 0xe8, 0xbc, 0xd1, 0x8a, 0x33, 0xd8, 0xe8, 0x36, 0x80, 0xa7, 0x64, + 0x46, 0x69, 0x98, 0x2d, 0xe6, 0xb2, 0xbd, 0x1d, 0xb1, 0x30, 0x3b, 0x33, 0x4a, 0x9f, 0x63, 0xfa, + 0x1b, 0x6b, 0xfc, 0xe8, 0xfa, 0x54, 0x49, 0x83, 0x24, 0xa4, 0x5a, 0x1a, 0x61, 0x13, 0x56, 0xeb, + 0x33, 0xc7, 0xc1, 0x58, 0xb6, 0xbb, 0x7f, 0xab, 0x00, 0x1a, 0x15, 0x34, 0x03, 0x03, 0x42, 0xae, + 0x89, 0x57, 0x72, 0xe6, 0x29, 0xf9, 0x1c, 0xe4, 0x13, 0xbc, 0xb3, 0x97, 0x2b, 0x0f, 0x55, 0x3f, + 0xf4, 0x06, 0x0c, 0xb5, 0xc2, 0xea, 0x0a, 0x49, 0xbc, 0xaa, 0x97, 0x78, 0xe2, 0x34, 0xb7, 0x70, + 0xc2, 0x48, 0x8a, 0x33, 0x63, 0xf4, 0xd1, 0xad, 0xa5, 0x2c, 0xb0, 0xce, 0x0f, 0xbd, 0x00, 0x28, + 0x26, 0xd1, 0xb6, 0x5f, 0x21, 0xd3, 0x95, 0x0a, 0x55, 0x89, 0xd8, 0x0b, 0xd0, 0xc3, 0x26, 0x33, + 0x21, 0x26, 0x83, 0xca, 0x1d, 0x18, 0x38, 0xa7, 0x97, 0xfb, 0x66, 0x01, 0x46, 0xb5, 0xb9, 0xb6, + 0x48, 0x05, 0x7d, 0xc7, 0x81, 0x31, 0x75, 0x9c, 0xcd, 0xec, 0x5e, 0xa3, 0xbb, 0x8a, 0x1f, 0x56, + 0xc4, 0xe6, 0xf3, 0xa5, 0xbc, 0xd4, 0x4f, 0xc1, 0x87, 0xcb, 0xfa, 0xf3, 0x62, 0x0e, 0x63, 0x99, + 0x56, 0x9c, 0x1d, 0xd6, 0xc4, 0x57, 0x1c, 0x38, 0x93, 0x47, 0x22, 0x47, 0xe6, 0xd6, 0x75, 0x99, + 0x6b, 0x55, 0x78, 0x51, 0xae, 0x74, 0x32, 0xba, 0x1c, 0xff, 0xbf, 0x05, 0x18, 0xd7, 0xb7, 0x10, + 0xd3, 0x04, 0xfe, 0xb9, 0x03, 0x67, 0xe5, 0x0c, 0x30, 0x89, 0xdb, 0x8d, 0xcc, 0xf2, 0x36, 0xad, + 0x2e, 0x2f, 0x3f, 0x49, 0xa7, 0xf3, 0xf8, 0xf1, 0x65, 0x7e, 0x4c, 0x2c, 0xf3, 0xd9, 0x5c, 0x1c, + 0x9c, 0x3f, 0xd4, 0x89, 0x6f, 0x39, 0x30, 0xd1, 0x9d, 0x68, 0xce, 0xc2, 0xb7, 0xcc, 0x85, 0x7f, + 0xd9, 0xde, 0x24, 0x39, 0x7b, 0xb6, 0xfc, 0x6c, 0xb2, 0xfa, 0x03, 0xf8, 0xcd, 0x01, 0xe8, 0x38, + 0x43, 0xd0, 0x73, 0x30, 0x24, 0xc4, 0xf1, 0x72, 0x58, 0x8b, 0xd9, 0x20, 0x07, 0xf8, 0xbb, 0x36, + 0x9d, 0x82, 0xb1, 0x8e, 0x83, 0xaa, 0x50, 0x88, 0x2f, 0x8b, 0xa1, 0x5b, 0x10, 0x6f, 0xe5, 0xcb, + 0x4a, 0x8b, 0xec, 0xdb, 0xdf, 0x9b, 0x2c, 0x94, 0x2f, 0xe3, 0x42, 0x7c, 0x99, 0x6a, 0xea, 0x35, + 0x3f, 0xb1, 0xa7, 0xa9, 0x2f, 0xf8, 0x89, 0xe2, 0xc3, 0x34, 0xf5, 0x05, 0x3f, 0xc1, 0x94, 0x05, + 0xb5, 0x40, 0xea, 0x49, 0xd2, 0x62, 0x27, 0xbe, 0x15, 0x0b, 0xe4, 0xea, 0xfa, 0xfa, 0x9a, 0xe2, + 0xc5, 0xf4, 0x0b, 0x0a, 0xc1, 0x8c, 0x0b, 0xfa, 0x9c, 0x43, 0x57, 0x9c, 0x37, 0x86, 0xd1, 0xae, + 0x50, 0x1c, 0xae, 0xdb, 0xdb, 0x02, 0x61, 0xb4, 0xab, 0x98, 0x8b, 0x07, 0xa9, 0x1a, 0xb0, 0xce, + 0x9a, 0x4d, 0xbc, 0xba, 0x19, 0x33, 0x3d, 0xc1, 0xce, 0xc4, 0xe7, 0xe6, 0xcb, 0x99, 0x89, 0xcf, + 0xcd, 0x97, 0x31, 0xe3, 0x42, 0x1f, 0x68, 0xe4, 0xed, 0x08, 0x1d, 0xc3, 0xc2, 0x03, 0xc5, 0xde, + 0x8e, 0xf9, 0x40, 0xb1, 0xb7, 0x83, 0x29, 0x0b, 0xca, 0x29, 0x8c, 0x63, 0xa6, 0x52, 0x58, 0xe1, + 0xb4, 0x5a, 0x2e, 0x9b, 0x9c, 0x56, 0xcb, 0x65, 0x4c, 0x59, 0xb0, 0x4d, 0x5a, 0x89, 0x99, 0x3e, + 0x62, 0x67, 0x93, 0xce, 0x66, 0x38, 0x2d, 0xcc, 0x96, 0x31, 0x65, 0x41, 0x45, 0x86, 0xf7, 0x5a, + 0x3b, 0xe2, 0xca, 0xcc, 0xd0, 0xa5, 0x55, 0x0b, 0xfb, 0x85, 0x92, 0x53, 0xdc, 0x06, 0xf7, 0xf7, + 0x26, 0x8b, 0x0c, 0x84, 0x39, 0x23, 0xf7, 0x77, 0x7b, 0x52, 0x71, 0x21, 0xe5, 0x39, 0xfa, 0x9b, + 0xec, 0x20, 0x14, 0xb2, 0x40, 0xa8, 0xbe, 0xce, 0xb1, 0xa9, 0xbe, 0xa7, 0xf9, 0x89, 0x67, 0xb0, + 0xc3, 0x59, 0xfe, 0xe8, 0xd7, 0x9c, 0x4e, 0xdb, 0xd6, 0xb3, 0x7f, 0x96, 0xa5, 0x07, 0x33, 0x3f, + 0x2b, 0x0e, 0x34, 0x79, 0x27, 0x3e, 0xe7, 0xa4, 0x4a, 0x44, 0xdc, 0xed, 0x1c, 0xf8, 0x88, 0x79, + 0x0e, 0x58, 0x34, 0xc8, 0x75, 0xb9, 0xff, 0x79, 0x07, 0x46, 0x24, 0x9c, 0xaa, 0xc7, 0x31, 0xba, + 0x05, 0x03, 0x72, 0xa4, 0xe2, 0xe9, 0xd9, 0xf4, 0x05, 0x28, 0x25, 0x5e, 0x0d, 0x46, 0x71, 0x73, + 0xbf, 0xd3, 0x07, 0x28, 0x3d, 0xab, 0x5a, 0x61, 0xec, 0x33, 0x49, 0x74, 0x0f, 0xa7, 0x50, 0xa0, + 0x9d, 0x42, 0x37, 0x6c, 0x9e, 0x42, 0xe9, 0xb0, 0x8c, 0xf3, 0xe8, 0xd7, 0x32, 0x72, 0x9b, 0x1f, + 0x4c, 0x1f, 0x3e, 0x16, 0xb9, 0xad, 0x0d, 0xe1, 0x60, 0x09, 0xbe, 0x2d, 0x24, 0x38, 0x3f, 0xba, + 0x7e, 0xc9, 0xae, 0x04, 0xd7, 0x46, 0x91, 0x95, 0xe5, 0x11, 0x97, 0xb0, 0xfc, 0xec, 0xba, 0x69, + 0x55, 0xc2, 0x6a, 0x5c, 0x4d, 0x59, 0x1b, 0x71, 0x59, 0xdb, 0x67, 0x8b, 0xa7, 0x26, 0x6b, 0xb3, + 0x3c, 0x95, 0xd4, 0x7d, 0x4d, 0x4a, 0x5d, 0x7e, 0x6a, 0xbd, 0x64, 0x59, 0xea, 0x6a, 0x7c, 0x3b, + 0xe5, 0xef, 0x47, 0xe1, 0x6c, 0x27, 0x1e, 0x26, 0x9b, 0xe8, 0x22, 0x0c, 0x56, 0xc2, 0x60, 0xd3, + 0xaf, 0xad, 0x78, 0x2d, 0x61, 0xaf, 0x29, 0x59, 0x34, 0x2b, 0x1b, 0x70, 0x8a, 0x83, 0x1e, 0xe3, + 0x82, 0x87, 0x7b, 0x44, 0x86, 0x04, 0x6a, 0xcf, 0x12, 0xd9, 0x65, 0x52, 0xe8, 0x3d, 0x03, 0x5f, + 0xfd, 0xc6, 0xe4, 0x43, 0x9f, 0xf8, 0x77, 0x8f, 0x3f, 0xe4, 0xfe, 0x7e, 0x0f, 0x3c, 0x92, 0xcb, + 0x53, 0x68, 0xeb, 0xbf, 0x69, 0x68, 0xeb, 0x5a, 0xbb, 0x90, 0x22, 0x37, 0x6d, 0x2a, 0xb2, 0x1a, + 0xf9, 0x3c, 0xbd, 0x5c, 0x6b, 0xc6, 0xf9, 0x83, 0xa2, 0x0b, 0x15, 0x78, 0x4d, 0x12, 0xb7, 0xbc, + 0x0a, 0x11, 0xb3, 0x57, 0x0b, 0x75, 0x4d, 0x36, 0xe0, 0x14, 0x87, 0x9b, 0xd0, 0x9b, 0x5e, 0xbb, + 0x91, 0x08, 0x47, 0x99, 0x66, 0x42, 0x33, 0x30, 0x96, 0xed, 0xe8, 0x6f, 0x3b, 0x80, 0x3a, 0xb9, + 0x8a, 0x17, 0x71, 0xfd, 0x38, 0xd6, 0x61, 0xe6, 0xdc, 0xbe, 0x66, 0x84, 0x6b, 0x33, 0xcd, 0x19, + 0x87, 0xf6, 0x4c, 0x3f, 0x96, 0x9e, 0x43, 0xdc, 0x38, 0x38, 0x84, 0x0f, 0x8d, 0xb9, 0x5a, 0x2a, + 0x15, 0x12, 0xc7, 0xdc, 0x1d, 0xa7, 0xbb, 0x5a, 0x18, 0x18, 0xcb, 0x76, 0x34, 0x09, 0x45, 0x12, + 0x45, 0x61, 0x24, 0x6c, 0x6d, 0xb6, 0x8d, 0xaf, 0x50, 0x00, 0xe6, 0x70, 0xf7, 0x27, 0x05, 0x28, + 0x75, 0xb3, 0x4e, 0xd0, 0x6f, 0x69, 0x76, 0xb5, 0xb0, 0x9c, 0x84, 0xe1, 0x17, 0x1e, 0x9f, 0x4d, + 0x94, 0x35, 0x00, 0xbb, 0x58, 0xd8, 0xa2, 0x15, 0x67, 0x07, 0x38, 0xf1, 0x25, 0xcd, 0xc2, 0xd6, + 0x49, 0xe4, 0x1c, 0xf0, 0x9b, 0xe6, 0x01, 0xbf, 0x66, 0x7b, 0x52, 0xfa, 0x31, 0xff, 0x87, 0x45, + 0x38, 0x2d, 0x5b, 0xcb, 0x84, 0x1e, 0x95, 0x2f, 0xb6, 0x49, 0xb4, 0x8b, 0x7e, 0xe8, 0xc0, 0x19, + 0x2f, 0xeb, 0xba, 0xf1, 0xc9, 0x31, 0x2c, 0xb4, 0xc6, 0x75, 0x6a, 0x3a, 0x87, 0x23, 0x5f, 0xe8, + 0x4b, 0x62, 0xa1, 0xcf, 0xe4, 0xa1, 0x74, 0xf1, 0xbb, 0xe7, 0x4e, 0x00, 0x3d, 0x0f, 0xc3, 0x12, + 0xce, 0xdc, 0x3d, 0xfc, 0x15, 0x57, 0xce, 0xed, 0x69, 0xad, 0x0d, 0x1b, 0x98, 0xb4, 0x67, 0x42, + 0x9a, 0xad, 0x86, 0x97, 0x10, 0xcd, 0x51, 0xa4, 0x7a, 0xae, 0x6b, 0x6d, 0xd8, 0xc0, 0x44, 0x4f, + 0x41, 0x5f, 0x10, 0x56, 0xc9, 0x62, 0x55, 0x38, 0x88, 0x47, 0x45, 0x9f, 0xbe, 0x6b, 0x0c, 0x8a, + 0x45, 0x2b, 0x7a, 0x32, 0xf5, 0xc6, 0x15, 0xd9, 0x2b, 0x34, 0x94, 0xe7, 0x89, 0x43, 0x7f, 0xd7, + 0x81, 0x41, 0xda, 0x63, 0x7d, 0xb7, 0x45, 0xe8, 0xd9, 0x46, 0x9f, 0x48, 0xf5, 0x78, 0x9e, 0xc8, + 0x35, 0xc9, 0xc6, 0x74, 0x75, 0x0c, 0x2a, 0xf8, 0x27, 0xdf, 0x9a, 0x1c, 0x90, 0x3f, 0x70, 0x3a, + 0xaa, 0x89, 0x05, 0x78, 0xb8, 0xeb, 0xd3, 0x3c, 0x52, 0x28, 0xe0, 0x2f, 0xc1, 0xa8, 0x39, 0x88, + 0x23, 0xc5, 0x01, 0xfe, 0x99, 0xf6, 0xda, 0xf1, 0x79, 0x09, 0x79, 0xf6, 0xc0, 0xb4, 0x59, 0xb5, + 0x19, 0xe6, 0xc4, 0xd6, 0x33, 0x37, 0xc3, 0x9c, 0xd8, 0x0c, 0x73, 0xee, 0xef, 0x39, 0xe9, 0xab, + 0xa9, 0xa9, 0x79, 0xf4, 0x60, 0x6e, 0x47, 0x0d, 0x21, 0x88, 0xd5, 0xc1, 0x7c, 0x1d, 0x2f, 0x63, + 0x0a, 0x47, 0x5f, 0xd2, 0xa4, 0x23, 0xed, 0xd6, 0x16, 0x61, 0x0d, 0x4b, 0x2e, 0x7a, 0x83, 0x70, + 0xa7, 0xfc, 0x13, 0x0d, 0x38, 0x3b, 0x04, 0xf7, 0xc7, 0x0e, 0x3c, 0x76, 0xa0, 0xd2, 0x9a, 0x3b, + 0x70, 0xe7, 0x81, 0x0f, 0x9c, 0x1e, 0x6b, 0x11, 0x69, 0x85, 0xd7, 0xf1, 0xb2, 0x78, 0x5e, 0xea, + 0x58, 0xc3, 0x1c, 0x8c, 0x65, 0xbb, 0xfb, 0x43, 0x07, 0xb2, 0xf4, 0x90, 0x07, 0xa3, 0xed, 0x98, + 0x44, 0xf4, 0x84, 0x2c, 0x93, 0x4a, 0x44, 0xe4, 0x6e, 0x7b, 0x72, 0x8a, 0x07, 0xef, 0xe9, 0x80, + 0xa7, 0x2a, 0x61, 0x44, 0xa6, 0xb6, 0x9f, 0x9b, 0xe2, 0x18, 0x4b, 0x64, 0xb7, 0x4c, 0x1a, 0x84, + 0xd2, 0x98, 0x41, 0xfb, 0x7b, 0x93, 0xa3, 0xd7, 0x0d, 0x02, 0x38, 0x43, 0x90, 0xb2, 0x68, 0x79, + 0x71, 0xbc, 0x13, 0x46, 0x55, 0xc1, 0xa2, 0x70, 0x64, 0x16, 0x6b, 0x06, 0x01, 0x9c, 0x21, 0xe8, + 0xbe, 0x49, 0xad, 0x41, 0x5d, 0x09, 0x45, 0xdf, 0xa0, 0xaa, 0x0c, 0x85, 0xcc, 0x34, 0xc2, 0x8d, + 0xd9, 0x30, 0x48, 0x3c, 0x3f, 0x20, 0x32, 0xf6, 0xbf, 0x6e, 0x49, 0xe5, 0x35, 0x68, 0xa7, 0x2e, + 0xf9, 0xce, 0x36, 0x9c, 0x33, 0x16, 0xaa, 0xb2, 0x6c, 0x34, 0xc2, 0x8d, 0x6c, 0x50, 0x8f, 0x22, + 0x61, 0xd6, 0xe2, 0xfe, 0xcc, 0x81, 0xf3, 0x5d, 0x74, 0x6b, 0xf4, 0x15, 0x07, 0x46, 0x36, 0xde, + 0x16, 0x73, 0x33, 0x87, 0x81, 0xde, 0x07, 0xa3, 0x14, 0x40, 0x0f, 0x96, 0xf9, 0x30, 0x6a, 0x7a, + 0x89, 0x98, 0xa0, 0x0a, 0x38, 0xcd, 0x18, 0xad, 0x38, 0x83, 0xed, 0xfe, 0x7a, 0x01, 0x72, 0xb8, + 0xa0, 0x67, 0x61, 0x80, 0x04, 0xd5, 0x56, 0xe8, 0x07, 0x89, 0x90, 0x2d, 0x4a, 0x88, 0x5d, 0x11, + 0x70, 0xac, 0x30, 0x84, 0x39, 0x21, 0x16, 0xa6, 0xd0, 0x61, 0x4e, 0x88, 0x91, 0xa7, 0x38, 0xa8, + 0x06, 0xe3, 0x1e, 0x0f, 0x97, 0xb0, 0xbd, 0xc7, 0xb6, 0x69, 0xcf, 0x51, 0xb6, 0xe9, 0x19, 0x16, + 0xcd, 0xcc, 0x90, 0xc0, 0x1d, 0x44, 0xd1, 0xbb, 0x61, 0xa8, 0x1d, 0x93, 0xf2, 0xdc, 0xd2, 0x6c, + 0x44, 0xaa, 0xdc, 0xc8, 0xd5, 0xc2, 0x78, 0xd7, 0xd3, 0x26, 0xac, 0xe3, 0xb9, 0xff, 0xc2, 0x81, + 0xfe, 0x19, 0xaf, 0xb2, 0x15, 0x6e, 0x6e, 0xd2, 0xa5, 0xa8, 0xb6, 0xa3, 0xd4, 0x4f, 0xa5, 0x2d, + 0xc5, 0x9c, 0x80, 0x63, 0x85, 0x81, 0xd6, 0xa1, 0x8f, 0xbf, 0xf0, 0xe2, 0xb5, 0xfb, 0x45, 0x6d, + 0x3e, 0x2a, 0x2d, 0x87, 0x6d, 0x87, 0x76, 0xe2, 0x37, 0xa6, 0x78, 0x5a, 0xce, 0xd4, 0x62, 0x90, + 0xac, 0x46, 0xe5, 0x24, 0xf2, 0x83, 0xda, 0x0c, 0x50, 0xe9, 0x3f, 0xcf, 0x68, 0x60, 0x41, 0x8b, + 0x4e, 0xa3, 0xe9, 0xdd, 0x92, 0xec, 0x84, 0xae, 0xa1, 0xa6, 0xb1, 0x92, 0x36, 0x61, 0x1d, 0xcf, + 0xfd, 0x7d, 0x07, 0x06, 0x67, 0xbc, 0xd8, 0xaf, 0xfc, 0x19, 0x12, 0x3e, 0x1f, 0x82, 0xe2, 0xac, + 0x57, 0xa9, 0x13, 0x74, 0x3d, 0x6b, 0xc3, 0x0e, 0x5d, 0x7a, 0x3a, 0x8f, 0x8d, 0xb2, 0x67, 0x75, + 0x4e, 0x23, 0xdd, 0x2c, 0x5d, 0xf7, 0x2d, 0x07, 0x46, 0x67, 0x1b, 0x3e, 0x09, 0x92, 0x59, 0x12, + 0x25, 0x6c, 0xe1, 0x6a, 0x30, 0x5e, 0x51, 0x90, 0x7b, 0x59, 0x3a, 0xb6, 0x5b, 0x67, 0x33, 0x24, + 0x70, 0x07, 0x51, 0x54, 0x85, 0x31, 0x0e, 0x4b, 0xdf, 0x8a, 0x23, 0xad, 0x1f, 0x73, 0x76, 0xce, + 0x9a, 0x14, 0x70, 0x96, 0xa4, 0xfb, 0x53, 0x07, 0xce, 0xcf, 0x36, 0xda, 0x71, 0x42, 0xa2, 0x9b, + 0x42, 0x1a, 0x49, 0x6d, 0x15, 0x7d, 0x04, 0x06, 0x9a, 0x32, 0x00, 0xeb, 0xdc, 0x65, 0x03, 0x33, + 0x79, 0x46, 0xb1, 0xe9, 0x60, 0x56, 0x37, 0x5e, 0x25, 0x95, 0x64, 0x85, 0x24, 0x5e, 0x9a, 0x2d, + 0x90, 0xc2, 0xb0, 0xa2, 0x8a, 0x5a, 0xd0, 0x1b, 0xb7, 0x48, 0xc5, 0x5e, 0xb2, 0x96, 0x9c, 0x43, + 0xb9, 0x45, 0x2a, 0xa9, 0x5c, 0x67, 0xa1, 0x43, 0xc6, 0xc9, 0xfd, 0x5f, 0x0e, 0x3c, 0xd2, 0x65, + 0xbe, 0xcb, 0x7e, 0x9c, 0xa0, 0x57, 0x3a, 0xe6, 0x3c, 0x75, 0xb8, 0x39, 0xd3, 0xde, 0x6c, 0xc6, + 0x4a, 0x20, 0x48, 0x88, 0x36, 0xdf, 0x8f, 0x41, 0xd1, 0x4f, 0x48, 0x53, 0x7a, 0x95, 0x2d, 0xf8, + 0x7f, 0xba, 0xcc, 0x65, 0x66, 0x44, 0xa6, 0xec, 0x2d, 0x52, 0x7e, 0x98, 0xb3, 0x75, 0xb7, 0xa0, + 0x6f, 0x36, 0x6c, 0xb4, 0x9b, 0xc1, 0xe1, 0x12, 0x5f, 0x92, 0xdd, 0x16, 0xc9, 0x9e, 0x91, 0x4c, + 0x9b, 0x67, 0x2d, 0xd2, 0x0f, 0xd4, 0x93, 0xef, 0x07, 0x72, 0xff, 0xa5, 0x03, 0xf4, 0xad, 0xaa, + 0xfa, 0x22, 0x30, 0xc8, 0xc9, 0x71, 0x86, 0x8f, 0xe9, 0xe4, 0xee, 0xec, 0x4d, 0x8e, 0x28, 0x44, + 0x8d, 0xfe, 0x87, 0xa0, 0x2f, 0x66, 0x16, 0xb6, 0x18, 0xc3, 0xbc, 0x54, 0x87, 0xb9, 0xdd, 0x7d, + 0x67, 0x6f, 0xf2, 0x50, 0x59, 0x98, 0x53, 0x8a, 0xb6, 0x88, 0x61, 0x0a, 0xaa, 0x54, 0x7f, 0x6b, + 0x92, 0x38, 0xf6, 0x6a, 0xd2, 0x60, 0x53, 0xfa, 0xdb, 0x0a, 0x07, 0x63, 0xd9, 0xee, 0x7e, 0xd9, + 0x81, 0x11, 0x75, 0x78, 0x51, 0x6d, 0x1c, 0x5d, 0xd3, 0x8f, 0x39, 0xbe, 0x53, 0x1e, 0xeb, 0x22, + 0x71, 0xc4, 0x41, 0x7e, 0xf0, 0x29, 0xf8, 0x2e, 0x18, 0xae, 0x92, 0x16, 0x09, 0xaa, 0x24, 0xa8, + 0x50, 0x6b, 0x9a, 0xee, 0x90, 0xc1, 0x99, 0x71, 0x6a, 0x3e, 0xce, 0x69, 0x70, 0x6c, 0x60, 0xb9, + 0xdf, 0x74, 0xe0, 0x61, 0x45, 0xae, 0x4c, 0x12, 0x4c, 0x92, 0x68, 0x57, 0x65, 0x5d, 0x1e, 0xed, + 0xb4, 0xba, 0x49, 0xd5, 0xd9, 0x24, 0xe2, 0xcc, 0xef, 0xed, 0xb8, 0x1a, 0xe2, 0xca, 0x2f, 0x23, + 0x82, 0x25, 0x35, 0xf7, 0x57, 0x7b, 0xe0, 0x8c, 0x3e, 0x48, 0x25, 0x60, 0x7e, 0xd9, 0x01, 0x50, + 0x2b, 0x40, 0x0f, 0xe4, 0x1e, 0x3b, 0xa1, 0x28, 0xe3, 0x49, 0xa5, 0x22, 0x48, 0x81, 0x63, 0xac, + 0xb1, 0x45, 0x2f, 0xc1, 0xf0, 0x36, 0x7d, 0x29, 0xc8, 0x0a, 0x55, 0x17, 0xe2, 0x52, 0x0f, 0x1b, + 0xc6, 0x64, 0xde, 0xc3, 0xbc, 0x91, 0xe2, 0xa5, 0xd6, 0xbd, 0x06, 0x8c, 0xb1, 0x41, 0x8a, 0x1a, + 0x2e, 0x23, 0x91, 0xfe, 0x48, 0x84, 0x8b, 0xfb, 0x83, 0x16, 0xe7, 0x98, 0x7d, 0xea, 0x33, 0xa7, + 0xf6, 0xf7, 0x26, 0x47, 0x0c, 0x10, 0x36, 0x07, 0xe1, 0xbe, 0x04, 0x6c, 0x2d, 0xfc, 0xa0, 0x4d, + 0x56, 0x03, 0xf4, 0x84, 0x74, 0xb9, 0xf1, 0x30, 0x89, 0x92, 0x1c, 0xba, 0xdb, 0x8d, 0x9a, 0xa6, + 0x9b, 0x9e, 0xdf, 0x60, 0xd9, 0x88, 0x14, 0x4b, 0x99, 0xa6, 0xf3, 0x0c, 0x8a, 0x45, 0xab, 0x3b, + 0x05, 0xfd, 0xb3, 0x74, 0xee, 0x24, 0xa2, 0x74, 0xf5, 0x24, 0xe2, 0x11, 0x23, 0x89, 0x58, 0x26, + 0x0b, 0xaf, 0xc3, 0xd9, 0xd9, 0x88, 0x78, 0x09, 0x29, 0x5f, 0x9e, 0x69, 0x57, 0xb6, 0x48, 0xc2, + 0x33, 0xb5, 0x62, 0xf4, 0x5e, 0x18, 0x09, 0xd9, 0x91, 0xb1, 0x1c, 0x56, 0xb6, 0xfc, 0xa0, 0x26, + 0x3c, 0xa8, 0x67, 0x05, 0x95, 0x91, 0x55, 0xbd, 0x11, 0x9b, 0xb8, 0xee, 0x7f, 0x2c, 0xc0, 0xf0, + 0x6c, 0x14, 0x06, 0x52, 0x2c, 0x9e, 0xc0, 0x51, 0x96, 0x18, 0x47, 0x99, 0x85, 0xe8, 0xa5, 0x3e, + 0xfe, 0x6e, 0xc7, 0x19, 0xba, 0xad, 0x44, 0x64, 0x8f, 0x2d, 0x13, 0xc4, 0xe0, 0xcb, 0x68, 0xa7, + 0x0f, 0xdb, 0x14, 0xa0, 0xee, 0x7f, 0x72, 0x60, 0x5c, 0x47, 0x3f, 0x81, 0x13, 0x34, 0x36, 0x4f, + 0xd0, 0x6b, 0x76, 0xe7, 0xdb, 0xe5, 0xd8, 0xfc, 0x7c, 0x9f, 0x39, 0x4f, 0x16, 0xba, 0xfe, 0xaa, + 0x03, 0xc3, 0x3b, 0x1a, 0x40, 0x4c, 0xd6, 0xb6, 0x12, 0xf3, 0x0e, 0x29, 0x66, 0x74, 0xe8, 0x9d, + 0xcc, 0x6f, 0x6c, 0x8c, 0x84, 0xca, 0xfd, 0xb8, 0x52, 0x27, 0xd5, 0x76, 0x43, 0x1e, 0xdf, 0x6a, + 0x49, 0xcb, 0x02, 0x8e, 0x15, 0x06, 0x7a, 0x05, 0x4e, 0x55, 0xc2, 0xa0, 0xd2, 0x8e, 0x22, 0x12, + 0x54, 0x76, 0xd7, 0xd8, 0x95, 0x07, 0x71, 0x20, 0x4e, 0x89, 0x6e, 0xa7, 0x66, 0xb3, 0x08, 0x77, + 0xf2, 0x80, 0xb8, 0x93, 0x10, 0xf7, 0xfd, 0xc7, 0xf4, 0xc8, 0x12, 0x06, 0x97, 0xe6, 0xfb, 0x67, + 0x60, 0x2c, 0xdb, 0xd1, 0x75, 0x38, 0x1f, 0x27, 0x5e, 0x94, 0xf8, 0x41, 0x6d, 0x8e, 0x78, 0xd5, + 0x86, 0x1f, 0x50, 0x53, 0x22, 0x0c, 0xaa, 0x3c, 0x32, 0xd8, 0x33, 0xf3, 0xc8, 0xfe, 0xde, 0xe4, + 0xf9, 0x72, 0x3e, 0x0a, 0xee, 0xd6, 0x17, 0x7d, 0x08, 0x26, 0x44, 0x74, 0x61, 0xb3, 0xdd, 0x78, + 0x21, 0xdc, 0x88, 0xaf, 0xfa, 0x31, 0xb5, 0xe3, 0x97, 0xfd, 0xa6, 0x9f, 0xb0, 0xf8, 0x5f, 0x71, + 0xe6, 0xc2, 0xfe, 0xde, 0xe4, 0x44, 0xb9, 0x2b, 0x16, 0x3e, 0x80, 0x02, 0xc2, 0x70, 0x8e, 0x0b, + 0xbf, 0x0e, 0xda, 0xfd, 0x8c, 0xf6, 0xc4, 0xfe, 0xde, 0xe4, 0xb9, 0xf9, 0x5c, 0x0c, 0xdc, 0xa5, + 0x27, 0x7d, 0x82, 0x89, 0xdf, 0x24, 0xaf, 0x85, 0x01, 0x61, 0x79, 0x27, 0xda, 0x13, 0x5c, 0x17, + 0x70, 0xac, 0x30, 0xd0, 0xab, 0xe9, 0x4e, 0xa4, 0xaf, 0x8b, 0xc8, 0x1f, 0x39, 0xba, 0x84, 0x63, + 0xa6, 0xc9, 0x4d, 0x8d, 0x12, 0x4b, 0x8c, 0x34, 0x68, 0xbb, 0x7f, 0x50, 0x00, 0xd4, 0x29, 0x22, + 0xd0, 0x12, 0xf4, 0x79, 0x95, 0xc4, 0xdf, 0x96, 0x89, 0x76, 0x4f, 0xe4, 0x1d, 0x9f, 0x9c, 0x15, + 0x26, 0x9b, 0x84, 0xee, 0x10, 0x92, 0xca, 0x95, 0x69, 0xd6, 0x15, 0x0b, 0x12, 0x28, 0x84, 0x53, + 0x0d, 0x2f, 0x4e, 0xe4, 0x5e, 0xad, 0xd2, 0x29, 0x0b, 0xc1, 0xfa, 0xf3, 0x87, 0x9b, 0x14, 0xed, + 0x31, 0x73, 0x96, 0xee, 0xdc, 0xe5, 0x2c, 0x21, 0xdc, 0x49, 0x1b, 0x7d, 0x9c, 0xe9, 0x21, 0x5c, + 0x49, 0x94, 0x0a, 0xc0, 0x92, 0x95, 0x33, 0x9a, 0xd3, 0x34, 0x74, 0x10, 0xc1, 0x06, 0x6b, 0x2c, + 0xdd, 0x7f, 0x05, 0xd0, 0x3f, 0x37, 0xbd, 0xb0, 0xee, 0xc5, 0x5b, 0x87, 0x50, 0xcd, 0xe9, 0xee, + 0x10, 0x3a, 0x54, 0xf6, 0xfd, 0x96, 0xba, 0x15, 0x56, 0x18, 0x28, 0x80, 0x3e, 0x3f, 0xa0, 0x2f, + 0x44, 0x69, 0xd4, 0x96, 0x37, 0x5b, 0x99, 0x19, 0xcc, 0x3f, 0xb1, 0xc8, 0xa8, 0x63, 0xc1, 0x05, + 0xdd, 0x86, 0x41, 0x4f, 0x5e, 0x54, 0x11, 0xc7, 0xd2, 0x92, 0x0d, 0x37, 0xad, 0x20, 0xa9, 0x27, + 0xca, 0x08, 0x10, 0x4e, 0x19, 0xa2, 0x4f, 0x38, 0x30, 0x24, 0xa7, 0x8e, 0xc9, 0xa6, 0x88, 0xa0, + 0xae, 0xd8, 0x9b, 0x33, 0x26, 0x9b, 0x3c, 0x8b, 0x42, 0x03, 0x60, 0x9d, 0x65, 0x87, 0x2a, 0x5f, + 0x3c, 0x8c, 0x2a, 0x8f, 0x76, 0x60, 0x70, 0xc7, 0x4f, 0xea, 0xec, 0xe0, 0x11, 0x91, 0x9b, 0xf9, + 0xfb, 0x1f, 0x35, 0x25, 0x97, 0xae, 0xd8, 0x4d, 0xc9, 0x00, 0xa7, 0xbc, 0xd0, 0x45, 0xce, 0x98, + 0x5d, 0xf4, 0x61, 0x22, 0x6b, 0xd0, 0xec, 0xc0, 0x1a, 0x70, 0x8a, 0x43, 0x97, 0x78, 0x98, 0xfe, + 0x2a, 0x93, 0x8f, 0xb6, 0xe9, 0x7b, 0x2c, 0x32, 0xe3, 0x2c, 0xec, 0x2b, 0x49, 0x91, 0x2f, 0xd6, + 0x4d, 0x8d, 0x07, 0x36, 0x38, 0xd2, 0x77, 0x64, 0xa7, 0x4e, 0x02, 0x91, 0xb9, 0xaf, 0xde, 0x91, + 0x9b, 0x75, 0x12, 0x60, 0xd6, 0x82, 0x6e, 0x73, 0xd3, 0x82, 0xeb, 0xb8, 0x22, 0xcb, 0x6d, 0xd9, + 0x8e, 0xda, 0xcd, 0x69, 0xf2, 0xe4, 0xf9, 0xf4, 0x37, 0xd6, 0xf8, 0x51, 0x75, 0x39, 0x0c, 0xae, + 0xdc, 0xf2, 0x13, 0x91, 0xf2, 0xaf, 0x24, 0xdd, 0x2a, 0x83, 0x62, 0xd1, 0xca, 0x33, 0x04, 0xe8, + 0x26, 0x88, 0x59, 0x7e, 0xff, 0xa0, 0x9e, 0x21, 0xc0, 0xc0, 0x58, 0xb6, 0xa3, 0xbf, 0xe3, 0x40, + 0xb1, 0x1e, 0x86, 0x5b, 0x71, 0x69, 0x84, 0x6d, 0x0e, 0x0b, 0xaa, 0x9e, 0x90, 0x38, 0x53, 0x57, + 0x29, 0x59, 0xf3, 0x12, 0x53, 0x91, 0xc1, 0xee, 0xec, 0x4d, 0x8e, 0x2e, 0xfb, 0x9b, 0xa4, 0xb2, + 0x5b, 0x69, 0x10, 0x06, 0xf9, 0xe4, 0x5b, 0x1a, 0xe4, 0xca, 0x36, 0x09, 0x12, 0xcc, 0x47, 0x35, + 0xf1, 0x79, 0x07, 0x20, 0x25, 0x94, 0x13, 0x8a, 0x23, 0x66, 0xf0, 0xda, 0x82, 0x9d, 0x67, 0x0c, + 0x4d, 0x8f, 0xed, 0xfd, 0x6b, 0x07, 0x86, 0xe8, 0xe4, 0xa4, 0x08, 0x7c, 0x0a, 0xfa, 0x12, 0x2f, + 0xaa, 0x11, 0xe9, 0xbf, 0x56, 0x8f, 0x63, 0x9d, 0x41, 0xb1, 0x68, 0x45, 0x01, 0x14, 0x13, 0x2f, + 0xde, 0x92, 0xda, 0xe5, 0xa2, 0xb5, 0x25, 0x4e, 0x15, 0x4b, 0xfa, 0x2b, 0xc6, 0x9c, 0x0d, 0x7a, + 0x1a, 0x06, 0xa8, 0x02, 0x30, 0xef, 0xc5, 0x32, 0x43, 0x64, 0x98, 0x0a, 0xf1, 0x79, 0x01, 0xc3, + 0xaa, 0xd5, 0xfd, 0xf5, 0x02, 0xf4, 0xce, 0x71, 0x3b, 0xa3, 0x2f, 0x0e, 0xdb, 0x51, 0x85, 0x08, + 0x7d, 0xd3, 0xc2, 0x9e, 0xa6, 0x74, 0xcb, 0x8c, 0xa6, 0xa6, 0xe9, 0xb3, 0xdf, 0x58, 0xf0, 0xa2, + 0x86, 0xec, 0x68, 0x12, 0x79, 0x41, 0xbc, 0xc9, 0x22, 0x05, 0x7e, 0x18, 0x88, 0x25, 0xb2, 0xb0, + 0x0b, 0xd7, 0x0d, 0xba, 0xe5, 0x84, 0xb4, 0xd2, 0x80, 0x85, 0xd9, 0x86, 0x33, 0x63, 0x70, 0x7f, + 0xc3, 0x01, 0x48, 0x47, 0x8f, 0x3e, 0xe7, 0xc0, 0x88, 0xa7, 0x67, 0x26, 0x8a, 0x35, 0x5a, 0xb5, + 0x17, 0x25, 0x64, 0x64, 0xb9, 0x89, 0x6d, 0x80, 0xb0, 0xc9, 0xd8, 0x7d, 0x37, 0x14, 0xd9, 0xdb, + 0xc1, 0x74, 0x71, 0xe1, 0x92, 0xcd, 0xfa, 0x60, 0xa4, 0xab, 0x16, 0x2b, 0x0c, 0xf7, 0x15, 0x18, + 0xbd, 0x72, 0x8b, 0x54, 0xda, 0x49, 0x18, 0x71, 0x87, 0x74, 0x97, 0x9b, 0x28, 0xce, 0x3d, 0xdd, + 0x44, 0xf9, 0xae, 0x03, 0x43, 0x5a, 0x9a, 0x1a, 0x3d, 0xa9, 0x6b, 0xb3, 0x65, 0x6e, 0x77, 0x8b, + 0xa5, 0x5a, 0xb2, 0x92, 0x08, 0xc7, 0x49, 0xa6, 0xc7, 0x88, 0x02, 0xe1, 0x94, 0xe1, 0x5d, 0xd2, + 0xc8, 0xdc, 0xdf, 0x75, 0xe0, 0x6c, 0x6e, 0x4e, 0xdd, 0x03, 0x1e, 0xf6, 0x45, 0x18, 0xdc, 0x22, + 0xbb, 0x46, 0x7c, 0x4d, 0x75, 0x58, 0x92, 0x0d, 0x38, 0xc5, 0x71, 0xbf, 0xe7, 0x40, 0x4a, 0x89, + 0x8a, 0xa2, 0x8d, 0x74, 0xe4, 0x9a, 0x28, 0x12, 0x9c, 0x44, 0x2b, 0xba, 0x0d, 0xe7, 0xcd, 0x27, + 0x78, 0x8f, 0x61, 0x00, 0x6e, 0x33, 0xe5, 0x53, 0xc2, 0xdd, 0x58, 0xb8, 0x37, 0xa0, 0xb8, 0xe0, + 0xb5, 0x6b, 0xe4, 0x50, 0x4e, 0x1c, 0x2a, 0xc6, 0x22, 0xe2, 0x35, 0x12, 0xa9, 0xa6, 0x0b, 0x31, + 0x86, 0x05, 0x0c, 0xab, 0x56, 0xf7, 0x87, 0x45, 0x18, 0xd2, 0x6e, 0x4e, 0xd0, 0x73, 0x3c, 0x22, + 0xad, 0x30, 0xab, 0xeb, 0xd2, 0x87, 0x8d, 0x59, 0x0b, 0x7d, 0x7f, 0x22, 0xb2, 0xed, 0xc7, 0x5c, + 0xe4, 0x18, 0xef, 0x0f, 0x16, 0x70, 0xac, 0x30, 0xd0, 0x24, 0x14, 0xab, 0xa4, 0x95, 0xd4, 0x99, + 0x34, 0xed, 0xe5, 0xe9, 0x63, 0x73, 0x14, 0x80, 0x39, 0x9c, 0x22, 0x6c, 0x92, 0xa4, 0x52, 0x67, + 0xce, 0x46, 0x91, 0x5f, 0x36, 0x4f, 0x01, 0x98, 0xc3, 0x73, 0x02, 0x63, 0xc5, 0xe3, 0x0f, 0x8c, + 0xf5, 0x59, 0x0e, 0x8c, 0xa1, 0x16, 0x9c, 0x8e, 0xe3, 0xfa, 0x5a, 0xe4, 0x6f, 0x7b, 0x09, 0x49, + 0x77, 0x4e, 0xff, 0x51, 0xf8, 0x9c, 0x67, 0x77, 0x99, 0xcb, 0x57, 0xb3, 0x54, 0x70, 0x1e, 0x69, + 0x54, 0x86, 0xb3, 0x7e, 0x10, 0x93, 0x4a, 0x3b, 0x22, 0x8b, 0xb5, 0x20, 0x8c, 0xc8, 0xd5, 0x30, + 0xa6, 0xe4, 0xc4, 0x4d, 0x4c, 0x95, 0x71, 0xb9, 0x98, 0x87, 0x84, 0xf3, 0xfb, 0xa2, 0x05, 0x38, + 0x55, 0xf5, 0x63, 0x6f, 0xa3, 0x41, 0xca, 0xed, 0x8d, 0x66, 0x48, 0x0d, 0x36, 0x7e, 0x3b, 0x62, + 0x60, 0xe6, 0x61, 0xe9, 0x9a, 0x98, 0xcb, 0x22, 0xe0, 0xce, 0x3e, 0xe8, 0x79, 0x18, 0x8e, 0xfd, + 0xa0, 0xd6, 0x20, 0x33, 0x91, 0x17, 0x54, 0xea, 0xe2, 0x0a, 0xa7, 0x72, 0xe1, 0x96, 0xb5, 0x36, + 0x6c, 0x60, 0xb2, 0xf7, 0x95, 0xf7, 0xc9, 0x68, 0x72, 0x02, 0x5b, 0xb4, 0xba, 0x3f, 0x72, 0x60, + 0x58, 0xcf, 0x76, 0xa6, 0x5a, 0x32, 0xd4, 0xe7, 0xe6, 0xcb, 0x5c, 0x8e, 0xdb, 0x3b, 0xad, 0xaf, + 0x2a, 0x9a, 0xa9, 0x55, 0x99, 0xc2, 0xb0, 0xc6, 0xf3, 0x10, 0x77, 0x97, 0x9f, 0x80, 0xe2, 0x66, + 0x48, 0x95, 0x89, 0x1e, 0xd3, 0xf7, 0x3b, 0x4f, 0x81, 0x98, 0xb7, 0xb9, 0xff, 0xc3, 0x81, 0x73, + 0xf9, 0x89, 0xdc, 0x6f, 0x87, 0x49, 0x5e, 0x02, 0xa0, 0x53, 0x31, 0x04, 0xb2, 0x56, 0xbd, 0x40, + 0xb6, 0x60, 0x0d, 0xeb, 0x70, 0xd3, 0xfe, 0x63, 0xaa, 0xd0, 0xa6, 0x7c, 0xbe, 0xe0, 0xc0, 0x08, + 0x65, 0xbb, 0x14, 0x6d, 0x18, 0xb3, 0x5d, 0xb5, 0x33, 0x5b, 0x45, 0x36, 0x75, 0x71, 0x1b, 0x60, + 0x6c, 0x32, 0x47, 0xbf, 0x00, 0x83, 0x5e, 0xb5, 0x1a, 0x91, 0x38, 0x56, 0xc1, 0x22, 0x16, 0xc7, + 0x9e, 0x96, 0x40, 0x9c, 0xb6, 0x53, 0x21, 0x5a, 0xaf, 0x6e, 0xc6, 0x54, 0x2e, 0x09, 0xcf, 0x9e, + 0x12, 0xa2, 0x94, 0x09, 0x85, 0x63, 0x85, 0xe1, 0xfe, 0xf5, 0x5e, 0x30, 0x79, 0xa3, 0x2a, 0x8c, + 0x6d, 0x45, 0x1b, 0xb3, 0x2c, 0xd6, 0x7e, 0x2f, 0x31, 0x6f, 0x16, 0x8b, 0x5e, 0x32, 0x29, 0xe0, + 0x2c, 0x49, 0xc1, 0x65, 0x89, 0xec, 0x26, 0xde, 0xc6, 0x3d, 0x47, 0xbc, 0x97, 0x4c, 0x0a, 0x38, + 0x4b, 0x12, 0xbd, 0x1b, 0x86, 0xb6, 0xa2, 0x0d, 0x29, 0xa2, 0xb3, 0xe9, 0x13, 0x4b, 0x69, 0x13, + 0xd6, 0xf1, 0xe8, 0x12, 0x6e, 0x45, 0x1b, 0xf4, 0x48, 0x93, 0x77, 0xf9, 0xd5, 0x12, 0x2e, 0x09, + 0x38, 0x56, 0x18, 0xa8, 0x05, 0x68, 0x4b, 0xae, 0x9e, 0xca, 0x2c, 0x10, 0x27, 0xc9, 0xe1, 0x13, + 0x13, 0x58, 0x86, 0xf6, 0x52, 0x07, 0x1d, 0x9c, 0x43, 0x1b, 0xbd, 0x04, 0xe7, 0xb7, 0xa2, 0x0d, + 0x71, 0xd0, 0xaf, 0x45, 0x7e, 0x50, 0xf1, 0x5b, 0xc6, 0xbd, 0xfd, 0x49, 0x31, 0xdc, 0xf3, 0x4b, + 0xf9, 0x68, 0xb8, 0x5b, 0x7f, 0xf7, 0xb7, 0x7a, 0x81, 0xdd, 0x38, 0xa4, 0xb2, 0xb0, 0x49, 0x92, + 0x7a, 0x58, 0xcd, 0xea, 0x2e, 0x2b, 0x0c, 0x8a, 0x45, 0xab, 0xcc, 0x43, 0x2c, 0x74, 0xc9, 0x43, + 0xdc, 0x81, 0xfe, 0x3a, 0xf1, 0xaa, 0x24, 0x92, 0xae, 0xb6, 0x65, 0x3b, 0x77, 0x24, 0xaf, 0x32, + 0xa2, 0xa9, 0x09, 0xcd, 0x7f, 0xc7, 0x58, 0x72, 0x43, 0xef, 0x81, 0x51, 0xaa, 0x85, 0x84, 0xed, + 0x44, 0xfa, 0x95, 0x7b, 0x99, 0x5f, 0x99, 0x9d, 0xa8, 0xeb, 0x46, 0x0b, 0xce, 0x60, 0xa2, 0x39, + 0x18, 0x17, 0x3e, 0x60, 0xe5, 0xc2, 0x13, 0x0b, 0xab, 0x0a, 0x2a, 0x94, 0x33, 0xed, 0xb8, 0xa3, + 0x07, 0x4b, 0x3c, 0x0b, 0xab, 0x3c, 0x0c, 0xa8, 0x27, 0x9e, 0x85, 0xd5, 0x5d, 0xcc, 0x5a, 0xd0, + 0x6b, 0x30, 0x40, 0xff, 0xce, 0x47, 0x61, 0x53, 0xf8, 0x55, 0xd6, 0xec, 0xac, 0x0e, 0xe5, 0x21, + 0xac, 0x3c, 0xa6, 0x9d, 0xcd, 0x08, 0x2e, 0x58, 0xf1, 0xa3, 0xb6, 0x86, 0x3c, 0x87, 0xcb, 0x5b, + 0x7e, 0xeb, 0x06, 0x89, 0xfc, 0xcd, 0x5d, 0xa6, 0x34, 0x0c, 0xa4, 0xb6, 0xc6, 0x62, 0x07, 0x06, + 0xce, 0xe9, 0xe5, 0x7e, 0xa1, 0x00, 0xc3, 0xfa, 0xc5, 0xd5, 0xbb, 0x25, 0xa7, 0xc6, 0xe9, 0xa6, + 0xe0, 0x96, 0xe5, 0x55, 0x0b, 0xd3, 0xbe, 0xdb, 0x86, 0xa8, 0x43, 0xaf, 0xd7, 0x16, 0xda, 0xa2, + 0x15, 0x07, 0x16, 0x9b, 0x71, 0x3b, 0xa9, 0xf3, 0x1b, 0x4e, 0x2c, 0x6d, 0x94, 0x71, 0x70, 0x3f, + 0xdd, 0x03, 0x03, 0xb2, 0x11, 0x7d, 0xca, 0x01, 0x48, 0xf3, 0x7d, 0x84, 0x28, 0x5d, 0xb3, 0x91, + 0x0c, 0xa2, 0xa7, 0x2a, 0x69, 0x4e, 0x67, 0x05, 0xc7, 0x1a, 0x5f, 0x94, 0x40, 0x5f, 0x48, 0x07, + 0x77, 0xc9, 0xde, 0xe5, 0xeb, 0x55, 0xca, 0xf8, 0x12, 0xe3, 0x9e, 0xba, 0xbc, 0x18, 0x0c, 0x0b, + 0x5e, 0xd4, 0x7a, 0xdb, 0x90, 0x69, 0x68, 0xf6, 0xdc, 0xc3, 0x2a, 0xb3, 0x2d, 0x35, 0xc6, 0x14, + 0x08, 0xa7, 0x0c, 0xdd, 0xe7, 0x60, 0xd4, 0x7c, 0x19, 0xa8, 0x45, 0xb0, 0xb1, 0x9b, 0x10, 0xee, + 0x2b, 0x18, 0xe6, 0x16, 0xc1, 0x0c, 0x05, 0x60, 0x0e, 0x77, 0xdf, 0xa4, 0x7a, 0x80, 0x12, 0x2f, + 0x87, 0x70, 0xcf, 0x3f, 0xa1, 0x3b, 0xba, 0xba, 0xd9, 0x4c, 0x1f, 0x87, 0x41, 0xf6, 0x0f, 0x7b, + 0xd1, 0x7b, 0x6c, 0x05, 0x8d, 0xd3, 0x71, 0x8a, 0x57, 0x9d, 0xe9, 0x04, 0x37, 0x24, 0x23, 0x9c, + 0xf2, 0x74, 0x43, 0x18, 0xcf, 0x62, 0xa3, 0x0f, 0xc2, 0x70, 0x2c, 0x8f, 0xd5, 0xf4, 0x1a, 0xd6, + 0x21, 0x8f, 0x5f, 0xe6, 0xb3, 0x2d, 0x6b, 0xdd, 0xb1, 0x41, 0xcc, 0x5d, 0x85, 0x3e, 0xab, 0x4b, + 0xe8, 0x7e, 0xdb, 0x81, 0x41, 0x16, 0x35, 0xab, 0x45, 0x5e, 0x33, 0xed, 0xd2, 0x73, 0xc0, 0xaa, + 0xc7, 0xd0, 0xcf, 0xed, 0x6b, 0x99, 0x6d, 0x62, 0x41, 0xca, 0xf0, 0x9a, 0x69, 0xa9, 0x94, 0xe1, + 0x86, 0x7c, 0x8c, 0x25, 0x27, 0xf7, 0x33, 0x05, 0xe8, 0x5b, 0x0c, 0x5a, 0xed, 0x3f, 0xf7, 0x75, + 0xbb, 0x56, 0xa0, 0x77, 0x31, 0x21, 0x4d, 0xb3, 0xbc, 0xdc, 0xf0, 0xcc, 0x93, 0x7a, 0x69, 0xb9, + 0x92, 0x59, 0x5a, 0x0e, 0x7b, 0x3b, 0x32, 0x19, 0x4b, 0xf8, 0x77, 0xd3, 0xab, 0x68, 0xcf, 0xc2, + 0xe0, 0xb2, 0xb7, 0x41, 0x1a, 0x4b, 0x64, 0x97, 0x5d, 0x1c, 0xe3, 0x89, 0x01, 0x4e, 0x6a, 0xd8, + 0x1b, 0x41, 0xfc, 0x39, 0x18, 0x65, 0xd8, 0xea, 0x65, 0xa0, 0x96, 0x03, 0x49, 0x6b, 0xf3, 0x38, + 0xa6, 0xe5, 0xa0, 0xd5, 0xe5, 0xd1, 0xb0, 0xdc, 0x29, 0x18, 0x4a, 0xa9, 0x1c, 0x82, 0xeb, 0xcf, + 0x0a, 0x30, 0x62, 0xb8, 0xa9, 0x8d, 0xe0, 0x9d, 0x73, 0xd7, 0xe0, 0x9d, 0x11, 0x4c, 0x2b, 0x3c, + 0xe8, 0x60, 0x5a, 0xcf, 0xc9, 0x07, 0xd3, 0xcc, 0x87, 0xd4, 0x7b, 0xa8, 0x87, 0xd4, 0x80, 0xde, + 0x65, 0x3f, 0xd8, 0x3a, 0x9c, 0x9c, 0x89, 0x2b, 0x61, 0xab, 0x43, 0xce, 0x94, 0x29, 0x10, 0xf3, + 0x36, 0xa9, 0xb9, 0xf4, 0xe4, 0x6b, 0x2e, 0xee, 0xa7, 0x1c, 0x18, 0x5e, 0xf1, 0x02, 0x7f, 0x93, + 0xc4, 0x09, 0xdb, 0x57, 0xc9, 0xb1, 0x5e, 0x20, 0x1a, 0xee, 0x72, 0x15, 0xfe, 0x93, 0x0e, 0x9c, + 0x5a, 0x21, 0xcd, 0xd0, 0x7f, 0xcd, 0x4b, 0x73, 0x1d, 0xe9, 0xd8, 0xeb, 0x7e, 0x22, 0x52, 0xbb, + 0xd4, 0xd8, 0xaf, 0xfa, 0x09, 0xa6, 0xf0, 0xbb, 0xf8, 0x60, 0x59, 0x2e, 0x3f, 0x35, 0xd0, 0xb4, + 0x4b, 0x6d, 0x69, 0x16, 0xa3, 0x6c, 0xc0, 0x29, 0x8e, 0xfb, 0xdb, 0x0e, 0xf4, 0xf3, 0x41, 0xa8, + 0xf4, 0x50, 0xa7, 0x0b, 0xed, 0x3a, 0x14, 0x59, 0x3f, 0xb1, 0xab, 0x17, 0x2c, 0xa8, 0x3f, 0x94, + 0x1c, 0x7f, 0x07, 0xd9, 0xbf, 0x98, 0x33, 0x60, 0x66, 0x8b, 0x77, 0x6b, 0x5a, 0xa5, 0x79, 0xa6, + 0x66, 0x0b, 0x83, 0x62, 0xd1, 0xea, 0x7e, 0xbd, 0x07, 0x06, 0x54, 0x05, 0x28, 0x76, 0x3f, 0x3f, + 0x08, 0xc2, 0xc4, 0xe3, 0x49, 0x01, 0x5c, 0x56, 0x7f, 0xd0, 0x5e, 0x05, 0xaa, 0xa9, 0xe9, 0x94, + 0x3a, 0x8f, 0xbd, 0x29, 0x23, 0x54, 0x6b, 0xc1, 0xfa, 0x20, 0xd0, 0xc7, 0xa0, 0xaf, 0x41, 0xa5, + 0x8f, 0x14, 0xdd, 0x37, 0x2c, 0x0e, 0x87, 0x89, 0x35, 0x31, 0x12, 0xb5, 0x42, 0x1c, 0x88, 0x05, + 0xd7, 0x89, 0xf7, 0xc1, 0x78, 0x76, 0xd4, 0x77, 0xbb, 0x73, 0x37, 0xa8, 0xdf, 0xd8, 0xfb, 0x8b, + 0x42, 0x7a, 0x1e, 0xbd, 0xab, 0xfb, 0x22, 0x0c, 0xad, 0x90, 0x24, 0xf2, 0x2b, 0x8c, 0xc0, 0xdd, + 0x36, 0xd7, 0xa1, 0xf4, 0x87, 0xcf, 0xb2, 0xcd, 0x4a, 0x69, 0xc6, 0xe8, 0x36, 0x40, 0x2b, 0x0a, + 0xa9, 0xfd, 0x4a, 0xda, 0xf2, 0x61, 0x5b, 0xd0, 0x87, 0xd7, 0x14, 0x4d, 0x1e, 0x2e, 0x4e, 0x7f, + 0x63, 0x8d, 0x9f, 0xfb, 0x0c, 0x14, 0x57, 0xda, 0x09, 0xb9, 0x75, 0x77, 0x89, 0xe5, 0x7e, 0x10, + 0x86, 0x19, 0xea, 0xd5, 0xb0, 0x41, 0x4f, 0x49, 0x3a, 0xd3, 0x26, 0xfd, 0x9d, 0x75, 0xd0, 0x33, + 0x24, 0xcc, 0xdb, 0xe8, 0x1b, 0x50, 0x0f, 0x1b, 0x55, 0x75, 0x21, 0x47, 0x3d, 0xdf, 0xab, 0x0c, + 0x8a, 0x45, 0xab, 0xfb, 0xcb, 0x05, 0x18, 0x62, 0x1d, 0x85, 0xf4, 0xd8, 0x85, 0xfe, 0x3a, 0xe7, + 0x23, 0x96, 0xc4, 0x42, 0x76, 0x9b, 0x3e, 0x7a, 0xcd, 0x34, 0xe3, 0x00, 0x2c, 0xf9, 0x51, 0xd6, + 0x3b, 0x9e, 0x9f, 0x50, 0xd6, 0x85, 0xe3, 0x65, 0x7d, 0x93, 0xb3, 0xc1, 0x92, 0x9f, 0xfb, 0xe5, + 0x02, 0x00, 0xab, 0xcf, 0xc5, 0xef, 0x83, 0xfe, 0x22, 0x14, 0x5b, 0x75, 0x2f, 0xce, 0x06, 0xdd, + 0x8a, 0x6b, 0x14, 0x78, 0x47, 0xdc, 0x78, 0x65, 0x3f, 0x30, 0x47, 0xd4, 0x13, 0xcb, 0x0b, 0x07, + 0x27, 0x96, 0xa3, 0x16, 0xf4, 0x87, 0xed, 0x84, 0xea, 0x86, 0xe2, 0x70, 0xb5, 0x10, 0x73, 0x5e, + 0xe5, 0x04, 0x79, 0x36, 0xb6, 0xf8, 0x81, 0x25, 0x1b, 0xf4, 0x3c, 0x0c, 0xb4, 0xa2, 0xb0, 0x46, + 0xcf, 0x4a, 0x71, 0x9c, 0x3e, 0x2a, 0xf5, 0x8f, 0x35, 0x01, 0xbf, 0xa3, 0xfd, 0x8f, 0x15, 0xb6, + 0xfb, 0x93, 0x31, 0xbe, 0x2e, 0x62, 0x73, 0x4c, 0x40, 0xc1, 0x97, 0x9e, 0x20, 0x10, 0x24, 0x0a, + 0x8b, 0x73, 0xb8, 0xe0, 0x57, 0xd5, 0x3e, 0x2e, 0x74, 0x3d, 0x79, 0xdf, 0x0d, 0x43, 0x55, 0x3f, + 0x6e, 0x35, 0xbc, 0xdd, 0x6b, 0x39, 0x6e, 0xb8, 0xb9, 0xb4, 0x09, 0xeb, 0x78, 0xe8, 0x59, 0x71, + 0x8d, 0xa0, 0xd7, 0x70, 0xbd, 0xc8, 0x6b, 0x04, 0xe9, 0x7d, 0x63, 0x7e, 0x83, 0x20, 0x7b, 0x2f, + 0xbb, 0x78, 0xe8, 0x7b, 0xd9, 0x59, 0xcd, 0xa7, 0xef, 0xe4, 0x35, 0x9f, 0xf7, 0xc2, 0x88, 0xfc, + 0xc9, 0xd4, 0x91, 0xd2, 0x19, 0x36, 0x7a, 0xe5, 0x1e, 0x5e, 0xd7, 0x1b, 0xb1, 0x89, 0x9b, 0x6e, + 0xda, 0xfe, 0xc3, 0x6e, 0xda, 0x4b, 0x00, 0x1b, 0x61, 0x3b, 0xa8, 0x7a, 0xd1, 0xee, 0xe2, 0x9c, + 0x48, 0x3a, 0x54, 0x8a, 0xd6, 0x8c, 0x6a, 0xc1, 0x1a, 0x96, 0xbe, 0xd1, 0x07, 0xef, 0xb2, 0xd1, + 0x3f, 0x08, 0x83, 0x2c, 0x41, 0x93, 0x54, 0xa7, 0x13, 0x91, 0x8e, 0x73, 0x94, 0x5c, 0x3e, 0xa5, + 0x76, 0x94, 0x25, 0x11, 0x9c, 0xd2, 0x43, 0x1f, 0x02, 0xd8, 0xf4, 0x03, 0x3f, 0xae, 0x33, 0xea, + 0x43, 0x47, 0xa6, 0xae, 0xe6, 0x39, 0xaf, 0xa8, 0x60, 0x8d, 0x22, 0x7a, 0x05, 0x4e, 0x91, 0x38, + 0xf1, 0x9b, 0x5e, 0x42, 0xaa, 0xea, 0xe2, 0x5d, 0x89, 0xf9, 0x0e, 0x55, 0x8a, 0xec, 0x95, 0x2c, + 0xc2, 0x9d, 0x3c, 0x20, 0xee, 0x24, 0x64, 0xbc, 0x91, 0x13, 0x47, 0x79, 0x23, 0xd1, 0x9f, 0x38, + 0x70, 0x2a, 0x22, 0x3c, 0x47, 0x23, 0x56, 0x03, 0x3b, 0xcb, 0xe4, 0x65, 0xc5, 0x46, 0xe9, 0x6b, + 0x55, 0xe3, 0x02, 0x67, 0xb9, 0x70, 0x45, 0x81, 0xc8, 0xd9, 0x77, 0xb4, 0xdf, 0xc9, 0x03, 0x7e, + 0xf2, 0xad, 0xc9, 0xc9, 0xce, 0x12, 0xec, 0x8a, 0x38, 0x7d, 0xf3, 0xfe, 0xda, 0x5b, 0x93, 0xe3, + 0xf2, 0x77, 0xba, 0x68, 0x1d, 0x93, 0xa4, 0xe7, 0x5e, 0x2b, 0xac, 0x2e, 0xae, 0x89, 0xbc, 0x29, + 0x75, 0xee, 0xad, 0x51, 0x20, 0xe6, 0x6d, 0xe8, 0x69, 0x18, 0xa8, 0x7a, 0xa4, 0x19, 0x06, 0xaa, + 0x88, 0x29, 0xd3, 0x9e, 0xe7, 0x04, 0x0c, 0xab, 0x56, 0xd4, 0x80, 0x3e, 0x9f, 0x99, 0xe8, 0x22, + 0x49, 0xd2, 0x82, 0x5f, 0x80, 0x9b, 0xfc, 0x32, 0x45, 0x92, 0x09, 0x61, 0xc1, 0x43, 0x97, 0xfa, + 0x63, 0x27, 0x23, 0xf5, 0x9f, 0x86, 0x81, 0x4a, 0xdd, 0x6f, 0x54, 0x23, 0x12, 0x94, 0xc6, 0x99, + 0xad, 0xca, 0x56, 0x62, 0x56, 0xc0, 0xb0, 0x6a, 0x45, 0x7f, 0x01, 0x46, 0xc2, 0x76, 0xc2, 0x5e, + 0x72, 0xfa, 0xfc, 0xe3, 0xd2, 0x29, 0x86, 0xce, 0x52, 0x5e, 0x56, 0xf5, 0x06, 0x6c, 0xe2, 0x51, + 0x61, 0x5b, 0x0f, 0x63, 0x56, 0x18, 0x85, 0x09, 0xdb, 0x73, 0xa6, 0xb0, 0xbd, 0xaa, 0xb5, 0x61, + 0x03, 0x13, 0x7d, 0xd5, 0x81, 0x53, 0xcd, 0xac, 0xe9, 0x52, 0x3a, 0xcf, 0x56, 0xa6, 0x6c, 0x43, + 0xc5, 0xcd, 0x90, 0xe6, 0x99, 0xc1, 0x1d, 0x60, 0xdc, 0x39, 0x08, 0x56, 0xa2, 0x28, 0xde, 0x0d, + 0x2a, 0xf5, 0x28, 0x0c, 0xcc, 0xe1, 0x3d, 0x6c, 0xeb, 0x26, 0x0f, 0x7b, 0xcb, 0xf2, 0x58, 0xcc, + 0x3c, 0xbc, 0xbf, 0x37, 0x79, 0x36, 0xb7, 0x09, 0xe7, 0x0f, 0x6a, 0x62, 0x0e, 0xce, 0xe5, 0xbf, + 0xa9, 0x77, 0xd3, 0xb5, 0x7b, 0x74, 0x5d, 0x7b, 0x1e, 0x1e, 0xee, 0x3a, 0x28, 0x2a, 0xf3, 0xa5, + 0x62, 0xe6, 0x98, 0x32, 0xbf, 0x43, 0x91, 0x1a, 0x85, 0x61, 0xbd, 0x7a, 0xbe, 0xfb, 0x7f, 0x7a, + 0x00, 0x52, 0x0f, 0x31, 0xf2, 0x60, 0x94, 0x7b, 0xa3, 0x17, 0xe7, 0xee, 0xf9, 0x0e, 0xf2, 0xac, + 0x41, 0x00, 0x67, 0x08, 0xa2, 0x26, 0x20, 0x0e, 0xe1, 0xbf, 0xef, 0x25, 0xaa, 0xc8, 0x82, 0x70, + 0xb3, 0x1d, 0x44, 0x70, 0x0e, 0x61, 0x3a, 0xa3, 0x24, 0xdc, 0x22, 0xc1, 0x75, 0xbc, 0x7c, 0x2f, + 0x17, 0xd9, 0x79, 0x1c, 0xca, 0x20, 0x80, 0x33, 0x04, 0x91, 0x0b, 0x7d, 0xcc, 0x2b, 0x21, 0xd3, + 0x8a, 0x99, 0x78, 0x61, 0x67, 0x7e, 0x8c, 0x45, 0x0b, 0xfa, 0xb2, 0x03, 0xa3, 0xf2, 0x3e, 0x3e, + 0xf3, 0x03, 0xca, 0x84, 0xe2, 0xeb, 0xb6, 0x3c, 0xfc, 0x57, 0x74, 0xea, 0x69, 0xba, 0x9e, 0x01, + 0x8e, 0x71, 0x66, 0x10, 0xee, 0x4b, 0x70, 0x3a, 0xa7, 0xbb, 0x15, 0x5b, 0xee, 0xbb, 0x0e, 0x0c, + 0x69, 0x55, 0xdf, 0xd0, 0x6d, 0x18, 0x0c, 0xcb, 0xd6, 0x73, 0xc4, 0x56, 0xcb, 0x1d, 0x39, 0x62, + 0x0a, 0x84, 0x53, 0x86, 0x87, 0x49, 0x6d, 0xcb, 0x2d, 0x51, 0xf7, 0x80, 0x87, 0x7d, 0xe4, 0xd4, + 0xb6, 0x7f, 0xdb, 0x0b, 0x29, 0xa5, 0x23, 0xd6, 0x89, 0x48, 0x13, 0xe1, 0x0a, 0x07, 0x26, 0xc2, + 0x55, 0x61, 0xcc, 0x63, 0x51, 0xd4, 0x7b, 0xac, 0x0e, 0xc1, 0x8b, 0x7e, 0x9a, 0x14, 0x70, 0x96, + 0x24, 0xe5, 0x12, 0xa7, 0x5d, 0x19, 0x97, 0xde, 0x23, 0x73, 0x29, 0x9b, 0x14, 0x70, 0x96, 0x24, + 0x7a, 0x05, 0x4a, 0x15, 0x76, 0xdb, 0x91, 0xcf, 0x71, 0x71, 0xf3, 0x5a, 0x98, 0xac, 0x45, 0x24, + 0x26, 0x41, 0x22, 0xca, 0x3a, 0x3d, 0x2e, 0x56, 0xa1, 0x34, 0xdb, 0x05, 0x0f, 0x77, 0xa5, 0x40, + 0x0d, 0x06, 0x16, 0x86, 0xf5, 0x93, 0x5d, 0x26, 0x44, 0x44, 0x7c, 0x5a, 0x19, 0x0c, 0x65, 0xbd, + 0x11, 0x9b, 0xb8, 0xe8, 0x57, 0x1c, 0x18, 0x69, 0x48, 0x47, 0x35, 0x6e, 0x37, 0x64, 0x8d, 0x42, + 0x6c, 0x65, 0xfb, 0x2d, 0xeb, 0x94, 0xb9, 0x2e, 0x61, 0x80, 0xb0, 0xc9, 0xdb, 0x7d, 0xd3, 0x81, + 0xf1, 0x6c, 0x37, 0xb4, 0x05, 0x8f, 0x35, 0xbd, 0x68, 0x6b, 0x31, 0xd8, 0x8c, 0xd8, 0x3d, 0x80, + 0x84, 0x3f, 0xd5, 0xe9, 0xcd, 0x84, 0x44, 0x73, 0xde, 0x2e, 0x8f, 0xe0, 0x15, 0xd5, 0xd7, 0x6a, + 0x1e, 0x5b, 0x39, 0x08, 0x19, 0x1f, 0x4c, 0x0b, 0x95, 0xe1, 0x2c, 0x45, 0x60, 0x15, 0xb6, 0xfc, + 0x30, 0x48, 0x99, 0x14, 0x18, 0x13, 0x95, 0xcf, 0xb6, 0x92, 0x87, 0x84, 0xf3, 0xfb, 0xba, 0x03, + 0xd0, 0xc7, 0xef, 0x40, 0xb9, 0xff, 0xa6, 0x00, 0x52, 0x49, 0xfb, 0xf3, 0x1d, 0x14, 0xa2, 0x07, + 0x5a, 0xc4, 0x1c, 0x2d, 0xc2, 0x07, 0xc0, 0x0e, 0x34, 0x51, 0x8e, 0x4e, 0xb4, 0x50, 0xed, 0x95, + 0xdc, 0xf2, 0x93, 0xd9, 0xb0, 0x2a, 0x2d, 0x7f, 0xa6, 0xbd, 0x5e, 0x11, 0x30, 0xac, 0x5a, 0xdd, + 0x4f, 0x39, 0x30, 0x42, 0x67, 0xd9, 0x68, 0x90, 0x46, 0x39, 0x21, 0xad, 0x18, 0xc5, 0x50, 0x8c, + 0xe9, 0x3f, 0xf6, 0x3c, 0x58, 0xe9, 0xd5, 0x37, 0xd2, 0xd2, 0x42, 0x06, 0x94, 0x09, 0xe6, 0xbc, + 0xdc, 0xef, 0xf4, 0xc0, 0xa0, 0x5a, 0xec, 0x43, 0xc4, 0x21, 0x2e, 0xa5, 0x95, 0x22, 0xb9, 0x34, + 0x2c, 0x69, 0x55, 0x22, 0xa9, 0xb9, 0x3e, 0x1d, 0xec, 0xf2, 0x3b, 0xf6, 0x69, 0xc9, 0xc8, 0x67, + 0xcd, 0x80, 0xe7, 0x39, 0x3d, 0x8a, 0xa6, 0xe1, 0x8b, 0xc8, 0xe7, 0x2d, 0x3d, 0xde, 0xdc, 0x6b, + 0xeb, 0x64, 0x51, 0xc1, 0xb4, 0xee, 0x81, 0xe6, 0xcc, 0x47, 0x44, 0x8a, 0x87, 0xfa, 0x88, 0xc8, + 0x33, 0xd0, 0x4b, 0x82, 0x76, 0x93, 0xa9, 0x2d, 0x83, 0x4c, 0x5d, 0xef, 0xbd, 0x12, 0xb4, 0x9b, + 0xe6, 0xcc, 0x18, 0x0a, 0x7a, 0x1f, 0x0c, 0x55, 0x49, 0x5c, 0x89, 0x7c, 0x76, 0x71, 0x5c, 0xf8, + 0x3b, 0x1e, 0x65, 0x4e, 0xa4, 0x14, 0x6c, 0x76, 0xd4, 0x3b, 0xb8, 0xaf, 0x41, 0xdf, 0x5a, 0xa3, + 0x5d, 0xf3, 0x03, 0xd4, 0x82, 0x3e, 0x7e, 0x8d, 0x5c, 0x9c, 0xbc, 0x16, 0x6c, 0x40, 0xfe, 0xb6, + 0x6b, 0xb9, 0x10, 0xfc, 0x06, 0xa4, 0xe0, 0xe3, 0xfe, 0x53, 0x07, 0xa8, 0xc1, 0xba, 0x30, 0x8b, + 0xfe, 0x72, 0xc7, 0x37, 0x33, 0x7e, 0x2e, 0xe7, 0x9b, 0x19, 0x23, 0x0c, 0x39, 0xe7, 0x73, 0x19, + 0x0d, 0x18, 0x61, 0x2e, 0x7a, 0x79, 0x1e, 0x09, 0x15, 0xf7, 0xf2, 0x21, 0x6f, 0x5e, 0xeb, 0x5d, + 0x85, 0x74, 0xd6, 0x41, 0xd8, 0x24, 0xee, 0xfe, 0x4e, 0x2f, 0x68, 0x9e, 0xec, 0x43, 0x6c, 0xef, + 0x8f, 0x66, 0xe2, 0x16, 0x2b, 0x56, 0xe2, 0x16, 0x32, 0x18, 0xc0, 0x45, 0x86, 0x19, 0xaa, 0xa0, + 0x83, 0xaa, 0x93, 0x46, 0x4b, 0xbc, 0x1c, 0x6a, 0x50, 0x57, 0x49, 0xa3, 0x85, 0x59, 0x8b, 0xba, + 0x43, 0xd6, 0xdb, 0xf5, 0x0e, 0x59, 0x1d, 0x8a, 0x35, 0xaf, 0x5d, 0x23, 0x22, 0x71, 0xcf, 0x42, + 0x88, 0x8a, 0x25, 0xd5, 0xf3, 0x10, 0x15, 0xfb, 0x17, 0x73, 0x06, 0xf4, 0xed, 0xac, 0xcb, 0x4c, + 0x06, 0xe1, 0x6b, 0xb4, 0xf0, 0x76, 0xaa, 0xe4, 0x08, 0xfe, 0x76, 0xaa, 0x9f, 0x38, 0x65, 0x86, + 0x5a, 0xd0, 0x5f, 0xe1, 0x05, 0x1b, 0xc4, 0x81, 0xbf, 0x68, 0xe3, 0x92, 0x1c, 0x23, 0xc8, 0x5d, + 0x11, 0xe2, 0x07, 0x96, 0x6c, 0xdc, 0x8b, 0x30, 0xa4, 0xd5, 0xda, 0xa7, 0x8f, 0x41, 0xd5, 0x0a, + 0xd0, 0x1e, 0xc3, 0x9c, 0x97, 0x78, 0x98, 0xb5, 0xb8, 0xdf, 0xec, 0x05, 0xe5, 0x12, 0xd2, 0xaf, + 0x74, 0x79, 0x15, 0xad, 0xb2, 0x89, 0x71, 0x97, 0x38, 0x0c, 0xb0, 0x68, 0xa5, 0x4a, 0x51, 0x93, + 0x44, 0x35, 0x65, 0x84, 0x0a, 0xf9, 0xaa, 0x94, 0xa2, 0x15, 0xbd, 0x11, 0x9b, 0xb8, 0x54, 0xa3, + 0x6d, 0x8a, 0xc8, 0x6e, 0x36, 0x6f, 0x56, 0x46, 0x7c, 0xb1, 0xc2, 0x40, 0x9f, 0x72, 0x60, 0xb8, + 0xa9, 0x05, 0x82, 0x45, 0xfe, 0x9e, 0x8d, 0xc0, 0x85, 0x46, 0x95, 0xe7, 0xd9, 0xe8, 0x10, 0x6c, + 0x70, 0x45, 0x0b, 0x70, 0x2a, 0x26, 0xc9, 0xea, 0x4e, 0x40, 0x22, 0x75, 0xd5, 0x5a, 0xdc, 0xbd, + 0x57, 0x49, 0xf3, 0xe5, 0x2c, 0x02, 0xee, 0xec, 0x93, 0x9b, 0xf2, 0x58, 0x3c, 0x72, 0xca, 0xe3, + 0x1c, 0x8c, 0x6f, 0x7a, 0x7e, 0xa3, 0x1d, 0x91, 0xae, 0x89, 0x93, 0xf3, 0x99, 0x76, 0xdc, 0xd1, + 0x83, 0xdd, 0xdb, 0x68, 0x78, 0xb5, 0xb8, 0xd4, 0xaf, 0xdd, 0xdb, 0xa0, 0x00, 0xcc, 0xe1, 0xee, + 0x3f, 0x74, 0x80, 0x17, 0x3d, 0x99, 0xde, 0xdc, 0xf4, 0x03, 0x3f, 0xd9, 0x45, 0x5f, 0x73, 0x60, + 0x3c, 0x08, 0xab, 0x64, 0x3a, 0x48, 0x7c, 0x09, 0xb4, 0x57, 0x58, 0x9a, 0xf1, 0xba, 0x96, 0x21, + 0xcf, 0x6f, 0xd0, 0x67, 0xa1, 0xb8, 0x63, 0x18, 0xee, 0x79, 0x38, 0x9b, 0x4b, 0xc0, 0x7d, 0xb3, + 0x07, 0xcc, 0xda, 0x2d, 0xe8, 0x45, 0x28, 0x36, 0x58, 0x35, 0x01, 0xe7, 0x1e, 0x8b, 0xf2, 0xb0, + 0xb5, 0xe2, 0xe5, 0x06, 0x38, 0x25, 0x34, 0x07, 0x43, 0xac, 0x20, 0x8c, 0xa8, 0xf5, 0xc0, 0xdf, + 0x08, 0x37, 0xfd, 0x9e, 0x95, 0x6a, 0xba, 0x63, 0xfe, 0xc4, 0x7a, 0x37, 0xf4, 0x3a, 0xf4, 0x6f, + 0xf0, 0xb2, 0x78, 0xf6, 0x42, 0x57, 0xa2, 0xce, 0x1e, 0x53, 0x66, 0x64, 0xd1, 0xbd, 0x3b, 0xe9, + 0xbf, 0x58, 0x72, 0x44, 0xbb, 0x30, 0xe0, 0xc9, 0x67, 0xda, 0x6b, 0x2b, 0x0f, 0xdf, 0xd8, 0x3f, + 0x22, 0xd1, 0x42, 0x3e, 0x43, 0xc5, 0x2e, 0x93, 0x91, 0x52, 0x3c, 0x54, 0x46, 0xca, 0xb7, 0x1d, + 0x80, 0xf4, 0x93, 0x00, 0xe8, 0x16, 0x0c, 0xc4, 0x97, 0x0d, 0x2b, 0xdf, 0xc6, 0xe5, 0x69, 0x41, + 0x51, 0xbb, 0x60, 0x28, 0x20, 0x58, 0x71, 0xbb, 0x9b, 0x67, 0xe2, 0x67, 0x0e, 0x9c, 0xc9, 0xfb, + 0x74, 0xc1, 0x03, 0x1c, 0xf1, 0x51, 0x9d, 0x12, 0xa2, 0xc3, 0x5a, 0x44, 0x36, 0xfd, 0x5b, 0xd9, + 0xa4, 0x95, 0x25, 0xd9, 0x80, 0x53, 0x1c, 0xf7, 0x7b, 0x7d, 0xa0, 0x18, 0x1f, 0x93, 0x13, 0xe3, + 0x29, 0x6a, 0xe4, 0xd4, 0xd2, 0x72, 0x8d, 0x0a, 0x0f, 0x33, 0x28, 0x16, 0xad, 0xd4, 0xd0, 0x91, + 0xb9, 0xd4, 0x42, 0x64, 0xb3, 0x5d, 0x28, 0x73, 0xae, 0xb1, 0x6a, 0xcd, 0x73, 0x8b, 0x14, 0x4f, + 0xc4, 0x2d, 0xd2, 0x67, 0xdf, 0x2d, 0xf2, 0x0c, 0xf4, 0x47, 0x61, 0x83, 0x4c, 0xe3, 0x6b, 0x42, + 0x7d, 0x4f, 0x0b, 0xe9, 0x72, 0x30, 0x96, 0xed, 0xd9, 0x1a, 0x9e, 0x03, 0x87, 0xab, 0xe1, 0x89, + 0xbe, 0xe7, 0x1c, 0xe0, 0x79, 0x19, 0xb4, 0x75, 0x26, 0xe4, 0x56, 0xb2, 0x62, 0xb6, 0xc8, 0xbd, + 0xb8, 0x73, 0xbe, 0xee, 0xc0, 0x29, 0x12, 0x54, 0xa2, 0x5d, 0x46, 0x47, 0x50, 0x13, 0xa1, 0xd3, + 0xeb, 0x36, 0x5e, 0xbe, 0x2b, 0x59, 0xe2, 0x3c, 0x2e, 0xd2, 0x01, 0xc6, 0x9d, 0xc3, 0x70, 0x7f, + 0x52, 0x80, 0xd3, 0x39, 0x14, 0xd8, 0x35, 0x99, 0x26, 0xdd, 0x40, 0x8b, 0xd5, 0xec, 0xeb, 0xb3, + 0x24, 0xe0, 0x58, 0x61, 0xa0, 0x35, 0x38, 0xb3, 0xd5, 0x8c, 0x53, 0x2a, 0xb3, 0x61, 0x90, 0x90, + 0x5b, 0xf2, 0x65, 0x92, 0x51, 0xd0, 0x33, 0x4b, 0x39, 0x38, 0x38, 0xb7, 0x27, 0xd5, 0x36, 0x48, + 0xe0, 0x6d, 0x34, 0x48, 0xda, 0x24, 0x2e, 0x79, 0x29, 0x6d, 0xe3, 0x4a, 0xa6, 0x1d, 0x77, 0xf4, + 0x40, 0x9f, 0x73, 0xe0, 0x91, 0x98, 0x44, 0xdb, 0x24, 0x2a, 0xfb, 0x55, 0x32, 0xdb, 0x8e, 0x93, + 0xb0, 0x49, 0xa2, 0x7b, 0x74, 0x0d, 0x4e, 0xee, 0xef, 0x4d, 0x3e, 0x52, 0xee, 0x4e, 0x0d, 0x1f, + 0xc4, 0xca, 0xfd, 0x9c, 0x03, 0xa3, 0x65, 0x66, 0xac, 0x2a, 0xd5, 0xd7, 0x76, 0xe9, 0xc1, 0xa7, + 0x54, 0x49, 0x81, 0x8c, 0x10, 0x33, 0x8b, 0x00, 0xb8, 0xaf, 0xc2, 0x78, 0x99, 0x34, 0xbd, 0x56, + 0x9d, 0xdd, 0xd0, 0xe4, 0x69, 0x3a, 0x17, 0x61, 0x30, 0x96, 0xb0, 0xec, 0xc7, 0x43, 0x14, 0x32, + 0x4e, 0x71, 0xd0, 0x93, 0x3c, 0xa5, 0x48, 0xde, 0xf3, 0x18, 0xe4, 0x46, 0x02, 0xcf, 0x43, 0x8a, + 0xb1, 0x6c, 0x73, 0xff, 0x91, 0x03, 0xc3, 0x69, 0x7f, 0xb2, 0x89, 0x6a, 0x30, 0x56, 0xd1, 0xee, + 0x48, 0xa5, 0xd9, 0xe9, 0x87, 0xbf, 0x4e, 0xc5, 0x2b, 0xa2, 0x9a, 0x44, 0x70, 0x96, 0x2a, 0x7a, + 0x17, 0x0c, 0x47, 0x64, 0xc3, 0x6b, 0x78, 0x41, 0x85, 0x2c, 0xa9, 0xa3, 0x92, 0x29, 0xdd, 0x58, + 0x83, 0x63, 0x03, 0xcb, 0xfd, 0x62, 0x01, 0xc6, 0xd4, 0x78, 0x45, 0xa4, 0xec, 0x8d, 0x6c, 0xf6, + 0x14, 0xb6, 0x51, 0x21, 0xc5, 0x7c, 0x00, 0x07, 0x64, 0x50, 0xbd, 0x91, 0xcd, 0xa0, 0x3a, 0x56, + 0xf6, 0x1d, 0xc1, 0xbf, 0x6f, 0x17, 0x60, 0x40, 0xd5, 0x6b, 0x79, 0x11, 0x8a, 0xcc, 0xfc, 0xbb, + 0x3f, 0x25, 0x96, 0x99, 0x92, 0x98, 0x53, 0xa2, 0x24, 0x59, 0x02, 0xc8, 0x3d, 0x17, 0xab, 0x1c, + 0xe4, 0x5e, 0x3b, 0x2f, 0x4a, 0x30, 0xa7, 0x84, 0x96, 0xa0, 0x87, 0x04, 0x55, 0xa1, 0xcd, 0x1e, + 0x9d, 0x20, 0xfb, 0xd6, 0xcf, 0x95, 0xa0, 0x8a, 0x29, 0x15, 0x56, 0x31, 0x91, 0x2b, 0x2d, 0x99, + 0x2f, 0x3b, 0x08, 0x8d, 0x45, 0xb4, 0xba, 0xbf, 0xd2, 0x03, 0x7d, 0xe5, 0xf6, 0x06, 0xd5, 0xcb, + 0xbf, 0xe5, 0xc0, 0xe9, 0x9d, 0x4c, 0x25, 0xd7, 0x74, 0xa3, 0x5f, 0xb7, 0xe7, 0xb9, 0xd4, 0x93, + 0x90, 0x1e, 0x91, 0x9f, 0xad, 0xce, 0x69, 0xc4, 0x79, 0xc3, 0x31, 0x8a, 0x29, 0xf6, 0x1c, 0x4b, + 0x31, 0xc5, 0x5b, 0xc7, 0x9c, 0xf5, 0x3e, 0xd2, 0x2d, 0xe3, 0xdd, 0xfd, 0x9d, 0x22, 0x00, 0x7f, + 0x1a, 0xab, 0xad, 0xe4, 0x30, 0xae, 0xad, 0xe7, 0x61, 0x58, 0x7e, 0x47, 0x3f, 0xef, 0xa3, 0x21, + 0x0b, 0x5a, 0x1b, 0x36, 0x30, 0x99, 0x1d, 0x11, 0x24, 0xd1, 0x2e, 0xd7, 0x35, 0xb3, 0x99, 0xed, + 0xaa, 0x05, 0x6b, 0x58, 0x68, 0xca, 0x08, 0x15, 0xf0, 0x08, 0xf0, 0xe8, 0x01, 0x9e, 0xfd, 0xf7, + 0xc1, 0xa8, 0x59, 0xe2, 0x41, 0x28, 0x58, 0x2a, 0x62, 0x6b, 0x56, 0x86, 0xc0, 0x19, 0x6c, 0xba, + 0x89, 0xab, 0xd1, 0x2e, 0x6e, 0x07, 0x42, 0xd3, 0x52, 0x9b, 0x78, 0x8e, 0x41, 0xb1, 0x68, 0x65, + 0xf7, 0xeb, 0xd9, 0x21, 0xc6, 0xe1, 0xe2, 0x8e, 0x7e, 0x7a, 0xbf, 0x5e, 0x6b, 0xc3, 0x06, 0x26, + 0xe5, 0x20, 0x5c, 0x83, 0x60, 0xbe, 0x26, 0x19, 0x7f, 0x5e, 0x0b, 0x46, 0x43, 0xd3, 0xa5, 0xc1, + 0xd3, 0xbc, 0xde, 0x75, 0xc8, 0xad, 0x67, 0xf4, 0xe5, 0x91, 0xf6, 0x8c, 0x07, 0x24, 0x43, 0x9f, + 0xaa, 0x9a, 0x7a, 0x02, 0xf8, 0xb0, 0x99, 0xa1, 0xd8, 0x35, 0x47, 0x7b, 0x0d, 0xce, 0xb4, 0xc2, + 0xea, 0x5a, 0xe4, 0x87, 0x91, 0x9f, 0xec, 0xce, 0x36, 0xbc, 0x38, 0x66, 0x1b, 0x63, 0xc4, 0xd4, + 0x69, 0xd6, 0x72, 0x70, 0x70, 0x6e, 0x4f, 0x6a, 0x14, 0xb4, 0x04, 0x90, 0x65, 0x27, 0x15, 0xb9, + 0x51, 0x20, 0x11, 0xb1, 0x6a, 0x75, 0x4f, 0xc3, 0xa9, 0x72, 0xbb, 0xd5, 0x6a, 0xf8, 0xa4, 0xaa, + 0x5c, 0xf1, 0xee, 0xfb, 0x61, 0x4c, 0x94, 0x5a, 0x54, 0x1a, 0xc4, 0x91, 0x0a, 0x03, 0xbb, 0x7f, + 0xe2, 0xc0, 0x58, 0x26, 0x17, 0x04, 0xbd, 0x9e, 0x3d, 0xf7, 0xad, 0xf8, 0xb9, 0xf4, 0x13, 0x9f, + 0xbf, 0xa4, 0xb9, 0x3a, 0x44, 0x5d, 0xe6, 0x3c, 0x5b, 0xbb, 0x3a, 0xc0, 0x32, 0x83, 0xf9, 0x89, + 0xa0, 0x27, 0x4e, 0xbb, 0x9f, 0x2d, 0x40, 0x7e, 0x02, 0x0e, 0xfa, 0x58, 0xe7, 0x02, 0xbc, 0x68, + 0x71, 0x01, 0x44, 0x06, 0x50, 0xf7, 0x35, 0x08, 0xcc, 0x35, 0x58, 0xb1, 0xb4, 0x06, 0x82, 0x6f, + 0xe7, 0x4a, 0xfc, 0x4f, 0x07, 0x86, 0xd6, 0xd7, 0x97, 0x95, 0x5b, 0x0a, 0xc3, 0xb9, 0x98, 0x5f, + 0x8d, 0x66, 0xe1, 0xcd, 0xd9, 0xb0, 0xd9, 0xe2, 0xd1, 0x4e, 0x11, 0x85, 0x65, 0x55, 0x2f, 0xcb, + 0xb9, 0x18, 0xb8, 0x4b, 0x4f, 0xb4, 0x08, 0xa7, 0xf5, 0x96, 0xb2, 0xf6, 0xcd, 0xb0, 0xa2, 0x28, + 0x47, 0xd2, 0xd9, 0x8c, 0xf3, 0xfa, 0x64, 0x49, 0x09, 0x0f, 0xa3, 0xf8, 0x46, 0x7f, 0x07, 0x29, + 0xd1, 0x8c, 0xf3, 0xfa, 0xb8, 0xab, 0x30, 0xb4, 0xee, 0x45, 0x6a, 0xe2, 0x1f, 0x80, 0xf1, 0x4a, + 0xd8, 0x94, 0x9e, 0x9d, 0x65, 0xb2, 0x4d, 0x1a, 0x62, 0xca, 0xbc, 0xb2, 0x7f, 0xa6, 0x0d, 0x77, + 0x60, 0xbb, 0xff, 0xed, 0x02, 0xa8, 0xab, 0x5e, 0x87, 0x38, 0x61, 0x5a, 0x2a, 0x35, 0xb1, 0x68, + 0x39, 0x35, 0x51, 0xc9, 0xda, 0x4c, 0x7a, 0x62, 0x92, 0xa6, 0x27, 0xf6, 0xd9, 0x4e, 0x4f, 0x54, + 0x0a, 0x63, 0x47, 0x8a, 0xe2, 0x57, 0x1c, 0x18, 0x0e, 0xc2, 0x2a, 0x51, 0x31, 0xac, 0x7e, 0xa6, + 0xb5, 0xbe, 0x62, 0x2f, 0xe7, 0x9a, 0xa7, 0xda, 0x09, 0xf2, 0x3c, 0x81, 0x55, 0x1d, 0x51, 0x7a, + 0x13, 0x36, 0xc6, 0x81, 0xe6, 0x35, 0x5f, 0x23, 0x77, 0xe9, 0x3f, 0x9a, 0x67, 0x73, 0xdc, 0xd5, + 0x71, 0x78, 0x4b, 0xd3, 0x9b, 0x06, 0xad, 0x7f, 0xd0, 0x3e, 0x8d, 0x4c, 0xc8, 0xc2, 0xad, 0xa9, + 0x3e, 0xe5, 0x42, 0x1f, 0xcf, 0x74, 0x15, 0x85, 0x6f, 0x58, 0xc0, 0x8c, 0x67, 0xc1, 0x62, 0xd1, + 0x82, 0x12, 0x19, 0x27, 0x1f, 0xb2, 0x55, 0x86, 0xdd, 0x88, 0xc3, 0xe7, 0x07, 0xca, 0xd1, 0x0b, + 0xba, 0x2d, 0x3b, 0x7c, 0x18, 0x5b, 0x76, 0xa4, 0xab, 0x1d, 0xfb, 0x05, 0x07, 0x86, 0x2b, 0x5a, + 0x59, 0xf4, 0xd2, 0xd3, 0xb6, 0xbe, 0xe6, 0x9a, 0x57, 0xbd, 0x9e, 0x9b, 0x84, 0x46, 0x19, 0x76, + 0x83, 0x3b, 0xab, 0xd4, 0xc7, 0x0c, 0x77, 0x76, 0xf4, 0x5b, 0xb9, 0xe0, 0x6f, 0x3a, 0x02, 0x64, + 0xee, 0x1f, 0x85, 0x61, 0xc1, 0x0b, 0xdd, 0x86, 0x01, 0x99, 0x2c, 0x2d, 0x52, 0x99, 0xb1, 0x0d, + 0xc7, 0xb8, 0x19, 0x7d, 0x93, 0xf5, 0xbd, 0x38, 0x14, 0x2b, 0x8e, 0xa8, 0x0e, 0x3d, 0x55, 0xaf, + 0x26, 0x92, 0x9a, 0x57, 0xec, 0x94, 0x4f, 0x94, 0x3c, 0x99, 0x79, 0x35, 0x37, 0xbd, 0x80, 0x29, + 0x0b, 0x74, 0x2b, 0xad, 0x2b, 0x3d, 0x6e, 0xed, 0xf4, 0x35, 0xd5, 0x24, 0xee, 0x9a, 0xe8, 0x28, + 0x53, 0x5d, 0x15, 0x01, 0xcb, 0xff, 0x8f, 0xb1, 0x9d, 0xb7, 0x53, 0x7f, 0x91, 0x17, 0x8c, 0x48, + 0x83, 0x9e, 0x94, 0x0b, 0xfb, 0x8a, 0xfc, 0xcf, 0xdb, 0xe2, 0xc2, 0xca, 0x1e, 0x64, 0xbf, 0x1e, + 0xdf, 0x80, 0xbe, 0x16, 0x4b, 0x7e, 0x28, 0xfd, 0x82, 0xad, 0xb3, 0x85, 0x27, 0x53, 0xf0, 0xbd, + 0xc9, 0xff, 0xc7, 0x82, 0x07, 0xba, 0x02, 0xfd, 0xfc, 0xf3, 0x08, 0x3c, 0xa9, 0x7c, 0xe8, 0xd2, + 0x44, 0xf7, 0x8f, 0x2c, 0xa4, 0x07, 0x05, 0xff, 0x1d, 0x63, 0xd9, 0x17, 0x7d, 0xd1, 0x81, 0x51, + 0x2a, 0x51, 0xd3, 0xef, 0x39, 0x94, 0x90, 0x2d, 0x99, 0x75, 0x3d, 0xa6, 0x1a, 0x89, 0x94, 0x35, + 0xca, 0x4c, 0x5a, 0x34, 0xd8, 0xe1, 0x0c, 0x7b, 0xf4, 0x06, 0x0c, 0xc4, 0x7e, 0x95, 0x54, 0xbc, + 0x28, 0x2e, 0x9d, 0x3e, 0x9e, 0xa1, 0xa4, 0x21, 0x12, 0xc1, 0x08, 0x2b, 0x96, 0xb9, 0x5f, 0x51, + 0x3f, 0xf3, 0x80, 0xbf, 0xa2, 0xfe, 0x57, 0x1d, 0x38, 0xcb, 0xcb, 0x79, 0x67, 0x6b, 0xb9, 0x9f, + 0xbd, 0x47, 0xf7, 0x0a, 0xcb, 0x86, 0x9f, 0xce, 0x23, 0x89, 0xf3, 0x39, 0xb1, 0x7a, 0xa0, 0xe6, + 0xe7, 0x37, 0xce, 0x59, 0x0d, 0x15, 0x1e, 0xfe, 0x93, 0x1b, 0xe8, 0x39, 0x18, 0x6a, 0x89, 0xe3, + 0xd0, 0x8f, 0x9b, 0xec, 0x6e, 0x43, 0x0f, 0xbf, 0xff, 0xb5, 0x96, 0x82, 0xb1, 0x8e, 0x63, 0x14, + 0x87, 0x7d, 0xe6, 0xa0, 0xe2, 0xb0, 0xe8, 0x3a, 0x0c, 0x25, 0x61, 0x83, 0x44, 0xc2, 0x52, 0x2d, + 0xb1, 0x1d, 0x78, 0x21, 0xef, 0xdd, 0x5a, 0x57, 0x68, 0xa9, 0x25, 0x9b, 0xc2, 0x62, 0xac, 0xd3, + 0x61, 0xf9, 0xa4, 0xa2, 0x4c, 0x7a, 0xc4, 0x4c, 0xd8, 0x87, 0x33, 0xf9, 0xa4, 0x7a, 0x23, 0x36, + 0x71, 0xd1, 0x02, 0x9c, 0x6a, 0x75, 0xd8, 0xc0, 0xfc, 0x76, 0x93, 0xca, 0x42, 0xe8, 0x34, 0x80, + 0x3b, 0xfb, 0x18, 0xd6, 0xef, 0x23, 0x07, 0x59, 0xbf, 0x5d, 0x4a, 0xa5, 0x3e, 0x7a, 0x2f, 0xa5, + 0x52, 0x51, 0x15, 0x1e, 0xf5, 0xda, 0x49, 0xc8, 0x4a, 0x7b, 0x98, 0x5d, 0x78, 0x6a, 0xed, 0xe3, + 0x3c, 0x5b, 0x77, 0x7f, 0x6f, 0xf2, 0xd1, 0xe9, 0x03, 0xf0, 0xf0, 0x81, 0x54, 0xd0, 0x6b, 0x30, + 0x40, 0x44, 0xb9, 0xd7, 0xd2, 0xcf, 0xd9, 0x52, 0x12, 0xcc, 0x02, 0xb2, 0x32, 0x53, 0x92, 0xc3, + 0xb0, 0xe2, 0x87, 0xd6, 0x61, 0xa8, 0x1e, 0xc6, 0xc9, 0x74, 0xc3, 0xf7, 0x62, 0x12, 0x97, 0x1e, + 0x63, 0x9b, 0x26, 0x57, 0xf7, 0xba, 0x2a, 0xd1, 0xd2, 0x3d, 0x73, 0x35, 0xed, 0x89, 0x75, 0x32, + 0x88, 0xb0, 0x80, 0x21, 0xcb, 0x2b, 0x96, 0xc1, 0x9c, 0x0b, 0x6c, 0x62, 0x4f, 0xe5, 0x51, 0x5e, + 0x0b, 0xab, 0x65, 0x13, 0x5b, 0x45, 0x0c, 0x75, 0x20, 0xce, 0xd2, 0x44, 0xcf, 0xc3, 0x70, 0x2b, + 0xac, 0x96, 0x5b, 0xa4, 0xb2, 0xe6, 0x25, 0x95, 0x7a, 0x69, 0xd2, 0xf4, 0xba, 0xad, 0x69, 0x6d, + 0xd8, 0xc0, 0x44, 0x2d, 0xe8, 0x6f, 0xf2, 0x3b, 0xdf, 0xa5, 0x27, 0x6c, 0xd9, 0x36, 0xe2, 0x12, + 0x39, 0xd7, 0x17, 0xc4, 0x0f, 0x2c, 0xd9, 0xa0, 0xbf, 0xe7, 0xc0, 0x58, 0xe6, 0xb6, 0x4e, 0xe9, + 0x1d, 0xd6, 0x54, 0x16, 0x93, 0xf0, 0xcc, 0x53, 0x6c, 0xf9, 0x4c, 0xe0, 0x9d, 0x4e, 0x10, 0xce, + 0x8e, 0x88, 0xaf, 0x0b, 0x2b, 0xdc, 0x50, 0x7a, 0xd2, 0xde, 0xba, 0x30, 0x82, 0x72, 0x5d, 0xd8, + 0x0f, 0x2c, 0xd9, 0xa0, 0x67, 0xa0, 0x5f, 0xd4, 0x58, 0x2b, 0x3d, 0x65, 0x46, 0x7d, 0x45, 0x29, + 0x36, 0x2c, 0xdb, 0x27, 0xde, 0x0f, 0xa7, 0x3a, 0x4c, 0xb7, 0x23, 0x55, 0x0f, 0xf8, 0x0d, 0x07, + 0xf4, 0x8b, 0xb6, 0xd6, 0xbf, 0xb1, 0xf0, 0x3c, 0x0c, 0x57, 0xf8, 0x97, 0xd8, 0xf8, 0x55, 0xdd, + 0x5e, 0xd3, 0xff, 0x39, 0xab, 0xb5, 0x61, 0x03, 0xd3, 0xbd, 0x0a, 0xa8, 0xb3, 0x00, 0xf6, 0x3d, + 0x95, 0xa6, 0xf9, 0x07, 0x0e, 0x8c, 0x18, 0x3a, 0x83, 0xf5, 0x40, 0xe1, 0x3c, 0xa0, 0xa6, 0x1f, + 0x45, 0x61, 0xa4, 0x7f, 0xf2, 0x4a, 0x54, 0xfc, 0x65, 0xd7, 0xa4, 0x56, 0x3a, 0x5a, 0x71, 0x4e, + 0x0f, 0xf7, 0x9f, 0xf4, 0x42, 0x9a, 0x2a, 0xac, 0xaa, 0x94, 0x3a, 0x5d, 0xab, 0x94, 0x3e, 0x0b, + 0x03, 0xaf, 0xc6, 0x61, 0xb0, 0x96, 0xd6, 0x32, 0x55, 0xcf, 0xe2, 0x85, 0xf2, 0xea, 0x35, 0x86, + 0xa9, 0x30, 0x18, 0xf6, 0x47, 0xe7, 0xfd, 0x46, 0xd2, 0x59, 0xec, 0xf2, 0x85, 0x17, 0x39, 0x1c, + 0x2b, 0x0c, 0xf6, 0xf5, 0xab, 0x6d, 0xa2, 0x1c, 0xe3, 0xe9, 0xd7, 0xaf, 0x78, 0x6d, 0x7b, 0xd6, + 0x86, 0x2e, 0xc2, 0xa0, 0x72, 0xaa, 0x0b, 0x4f, 0xbd, 0x5a, 0x29, 0xe5, 0x79, 0xc7, 0x29, 0x0e, + 0x53, 0x08, 0x85, 0x23, 0x56, 0xb8, 0x50, 0xca, 0x36, 0xcc, 0x93, 0x8c, 0x6b, 0x97, 0xcb, 0x76, + 0x09, 0xc6, 0x8a, 0x65, 0x5e, 0xb0, 0x74, 0xf0, 0x58, 0x82, 0xa5, 0x5a, 0xde, 0x7a, 0xf1, 0xb0, + 0x79, 0xeb, 0xe6, 0xde, 0x1e, 0x38, 0xd4, 0xde, 0xfe, 0x74, 0x0f, 0xf4, 0xdf, 0x20, 0x11, 0xab, + 0xf1, 0xfc, 0x0c, 0xf4, 0x6f, 0xf3, 0x7f, 0xb3, 0x17, 0x10, 0x05, 0x06, 0x96, 0xed, 0xf4, 0xb9, + 0x6d, 0xb4, 0xfd, 0x46, 0x75, 0x2e, 0x7d, 0x8b, 0xd3, 0xf2, 0x70, 0xb2, 0x01, 0xa7, 0x38, 0xb4, + 0x43, 0x8d, 0x6a, 0xf6, 0xcd, 0xa6, 0x9f, 0x64, 0x73, 0x87, 0x16, 0x64, 0x03, 0x4e, 0x71, 0xd0, + 0x53, 0xd0, 0x57, 0xf3, 0x93, 0x75, 0xaf, 0x96, 0x8d, 0xf2, 0x2d, 0x30, 0x28, 0x16, 0xad, 0x2c, + 0x4c, 0xe4, 0x27, 0xeb, 0x11, 0x61, 0x9e, 0xdd, 0x8e, 0x4a, 0x04, 0x0b, 0x5a, 0x1b, 0x36, 0x30, + 0xd9, 0x90, 0x42, 0x31, 0x33, 0x91, 0x38, 0x99, 0x0e, 0x49, 0x36, 0xe0, 0x14, 0x87, 0xee, 0xff, + 0x4a, 0xd8, 0x6c, 0xf9, 0x0d, 0x91, 0xd2, 0xab, 0xed, 0xff, 0x59, 0x01, 0xc7, 0x0a, 0x83, 0x62, + 0x53, 0x11, 0x46, 0xc5, 0x4f, 0xf6, 0x4b, 0x43, 0x6b, 0x02, 0x8e, 0x15, 0x86, 0x7b, 0x03, 0x46, + 0xf8, 0x9b, 0x3c, 0xdb, 0xf0, 0xfc, 0xe6, 0xc2, 0x2c, 0xba, 0xd2, 0x91, 0xb7, 0xfe, 0x4c, 0x4e, + 0xde, 0xfa, 0x59, 0xa3, 0x53, 0x67, 0xfe, 0xba, 0xfb, 0xa3, 0x02, 0x0c, 0x9c, 0xe0, 0xc7, 0xda, + 0x4e, 0xfc, 0xbb, 0xa3, 0xe8, 0x56, 0xe6, 0x43, 0x6d, 0x6b, 0x36, 0xaf, 0xa1, 0x1c, 0xf8, 0x91, + 0xb6, 0xff, 0x52, 0x80, 0x73, 0x12, 0x35, 0xfd, 0xee, 0x3e, 0xfb, 0xd2, 0xd0, 0xf1, 0x2f, 0x74, + 0x64, 0x2c, 0xf4, 0x9a, 0x3d, 0x6b, 0x74, 0x61, 0xb6, 0xeb, 0x52, 0xbf, 0x96, 0x59, 0x6a, 0x6c, + 0x95, 0xeb, 0xc1, 0x8b, 0xfd, 0xa7, 0x0e, 0x4c, 0xe4, 0x2f, 0xf6, 0x09, 0x7c, 0x1b, 0xef, 0x0d, + 0xf3, 0xdb, 0x78, 0xbf, 0x64, 0x6f, 0x8b, 0x99, 0x53, 0xe9, 0xf2, 0x95, 0xbc, 0x3f, 0x76, 0xe0, + 0x8c, 0xec, 0xc0, 0x4e, 0xcf, 0x19, 0x3f, 0x60, 0x89, 0x28, 0xc7, 0xbf, 0xcd, 0x6e, 0x1b, 0xdb, + 0xec, 0x65, 0x7b, 0x13, 0xd7, 0xe7, 0xd1, 0xf5, 0x9b, 0xc2, 0x7f, 0xe4, 0x40, 0x29, 0xaf, 0xc3, + 0x09, 0x3c, 0xf2, 0xd7, 0xcd, 0x47, 0x7e, 0xe3, 0x78, 0x66, 0xde, 0xfd, 0x81, 0x97, 0xba, 0x2d, + 0x14, 0x6a, 0x48, 0xbd, 0xca, 0xb1, 0x15, 0xa3, 0xe5, 0x2c, 0xf2, 0x15, 0xb4, 0x06, 0xf4, 0xc5, + 0x2c, 0x6b, 0x43, 0x6c, 0x81, 0xab, 0x36, 0xb4, 0x2d, 0x4a, 0x4f, 0xf8, 0xd8, 0xd9, 0xff, 0x58, + 0xf0, 0x70, 0xff, 0xd0, 0x81, 0xe1, 0x13, 0xfc, 0xe6, 0x65, 0x68, 0x3e, 0xe4, 0x17, 0xec, 0x3d, + 0xe4, 0x2e, 0x0f, 0x76, 0xaf, 0x08, 0x1d, 0x9f, 0x01, 0x44, 0x9f, 0x71, 0x54, 0xa6, 0x06, 0xcf, + 0x66, 0xfb, 0x90, 0xbd, 0x71, 0x1c, 0xa5, 0x08, 0x1d, 0xfa, 0x7a, 0xa6, 0x32, 0x5f, 0xc1, 0x56, + 0xb9, 0x9b, 0x8e, 0xd1, 0xdc, 0x43, 0x85, 0xbe, 0xaf, 0x38, 0x00, 0x7c, 0x9c, 0xa2, 0xb0, 0x2f, + 0x1d, 0xdb, 0xc6, 0xb1, 0xad, 0x14, 0x65, 0xc2, 0x87, 0xa6, 0x04, 0x64, 0xda, 0x80, 0xb5, 0x91, + 0xdc, 0x47, 0xe9, 0xbd, 0xfb, 0xae, 0xfa, 0xf7, 0x45, 0x07, 0xc6, 0x32, 0xc3, 0xcd, 0xe9, 0xbf, + 0x69, 0x7e, 0x1e, 0xcc, 0x82, 0xae, 0x60, 0x96, 0x7b, 0xd5, 0xdd, 0x01, 0x7b, 0x2e, 0x18, 0xdf, + 0x4f, 0x45, 0xaf, 0xc3, 0xa0, 0xb4, 0xe5, 0xe5, 0xf6, 0xb6, 0xf9, 0x99, 0x44, 0xa5, 0xb0, 0x4b, + 0x48, 0x8c, 0x53, 0x7e, 0x99, 0x44, 0xb0, 0xc2, 0xa1, 0x12, 0xc1, 0x1e, 0xec, 0x47, 0x16, 0xf3, + 0x3d, 0xad, 0xbd, 0xc7, 0xe2, 0x69, 0x7d, 0xd4, 0xba, 0xa7, 0xf5, 0xb1, 0x13, 0xf6, 0xb4, 0x6a, + 0x61, 0xaf, 0xe2, 0x7d, 0x84, 0xbd, 0x5e, 0x87, 0x33, 0xdb, 0xa9, 0x19, 0xa5, 0x76, 0x92, 0x28, + 0xed, 0xf2, 0x4c, 0xae, 0x7f, 0x95, 0x9a, 0x84, 0x71, 0x42, 0x82, 0x44, 0x33, 0xc0, 0xd2, 0x1c, + 0xb4, 0x1b, 0x39, 0xe4, 0x70, 0x2e, 0x93, 0x6c, 0xfc, 0xa2, 0xff, 0x10, 0xf1, 0x8b, 0xef, 0x38, + 0x70, 0xd6, 0xeb, 0xb8, 0x49, 0x84, 0xc9, 0xa6, 0x48, 0xa2, 0xb8, 0x69, 0x4f, 0x2f, 0x37, 0xc8, + 0x8b, 0x40, 0x51, 0x5e, 0x13, 0xce, 0x1f, 0x10, 0x7a, 0x32, 0x0d, 0x26, 0xf3, 0xcc, 0xc5, 0xfc, + 0xc8, 0xef, 0xd7, 0xb3, 0x19, 0x2a, 0xc0, 0x96, 0xfe, 0x23, 0x76, 0xed, 0x47, 0x0b, 0x59, 0x2a, + 0x43, 0xf7, 0x91, 0xa5, 0x92, 0x09, 0x26, 0x0d, 0x5b, 0x0a, 0x26, 0x05, 0x30, 0xee, 0x37, 0xbd, + 0x1a, 0x59, 0x6b, 0x37, 0x1a, 0xfc, 0x6a, 0x83, 0xfc, 0x90, 0x65, 0xae, 0x4f, 0x6a, 0x39, 0xac, + 0x78, 0x8d, 0xec, 0xf7, 0x82, 0xd5, 0x15, 0x8e, 0xc5, 0x0c, 0x25, 0xdc, 0x41, 0x9b, 0x6e, 0x58, + 0x56, 0x63, 0x8c, 0x24, 0x74, 0xb5, 0x59, 0x2a, 0xc4, 0x00, 0xdf, 0xb0, 0x57, 0x53, 0x30, 0xd6, + 0x71, 0xd0, 0x12, 0x0c, 0x56, 0x83, 0x58, 0x5c, 0x8a, 0x1c, 0x63, 0xc2, 0xec, 0x9d, 0x54, 0x04, + 0xce, 0x5d, 0x2b, 0xab, 0xeb, 0x90, 0x8f, 0xe6, 0x94, 0xaf, 0x53, 0xed, 0x38, 0xed, 0x8f, 0x56, + 0x18, 0x31, 0xf1, 0xa5, 0x20, 0x9e, 0xa1, 0xf0, 0x78, 0x97, 0x10, 0xc8, 0xdc, 0x35, 0xf9, 0xad, + 0xa3, 0x11, 0xc1, 0x4e, 0x7c, 0xf2, 0x27, 0xa5, 0xa0, 0x7d, 0x50, 0xf4, 0xd4, 0x81, 0x1f, 0x14, + 0x65, 0x75, 0x2b, 0x93, 0x86, 0x0a, 0x78, 0x5e, 0xb0, 0x56, 0xb7, 0x32, 0xcd, 0xfd, 0x13, 0x75, + 0x2b, 0x53, 0x00, 0xd6, 0x59, 0xa2, 0xd5, 0x6e, 0x81, 0xdf, 0xd3, 0x4c, 0x68, 0x1c, 0x3d, 0x8c, + 0xab, 0x47, 0x00, 0xcf, 0x1c, 0x18, 0x01, 0xec, 0x88, 0x58, 0x9e, 0x3d, 0x42, 0xc4, 0xb2, 0xce, + 0x2a, 0x0a, 0x2e, 0xcc, 0x8a, 0x20, 0xb1, 0x05, 0x8b, 0x85, 0x55, 0x6b, 0xe0, 0xb9, 0x94, 0xec, + 0x5f, 0xcc, 0x19, 0x74, 0x4d, 0x11, 0x3e, 0x7f, 0xcf, 0x29, 0xc2, 0x54, 0x3c, 0xa7, 0x70, 0x56, + 0x9a, 0xb2, 0x28, 0xc4, 0x73, 0x0a, 0xc6, 0x3a, 0x4e, 0x36, 0xfe, 0xf7, 0xf0, 0xb1, 0xc5, 0xff, + 0x26, 0x4e, 0x20, 0xfe, 0xf7, 0xc8, 0xa1, 0xe3, 0x7f, 0xb7, 0xe0, 0x74, 0x2b, 0xac, 0xce, 0xf9, + 0x71, 0xd4, 0x66, 0x77, 0xbd, 0x66, 0xda, 0xd5, 0x1a, 0x49, 0x58, 0x00, 0x71, 0xe8, 0xd2, 0x3b, + 0xf5, 0x41, 0xb6, 0xd8, 0x8b, 0x2c, 0xdf, 0xd1, 0x4c, 0x07, 0xe6, 0x0c, 0x60, 0x79, 0xa4, 0x39, + 0x8d, 0x38, 0x8f, 0x85, 0x1e, 0x79, 0x7c, 0xfc, 0x64, 0x22, 0x8f, 0x1f, 0x80, 0x81, 0xb8, 0xde, + 0x4e, 0xaa, 0xe1, 0x4e, 0xc0, 0xc2, 0xcb, 0x83, 0x33, 0xef, 0x50, 0xce, 0x59, 0x01, 0xbf, 0xb3, + 0x37, 0x39, 0x2e, 0xff, 0xd7, 0xfc, 0xb2, 0x02, 0x82, 0xbe, 0xd1, 0xe5, 0x46, 0x8a, 0x7b, 0x9c, + 0x37, 0x52, 0xce, 0x1f, 0xe9, 0x36, 0x4a, 0x5e, 0x78, 0xf5, 0x89, 0xb7, 0x5d, 0x78, 0xf5, 0x6b, + 0x0e, 0x8c, 0x6c, 0xeb, 0x4e, 0x70, 0x11, 0x02, 0xb6, 0x90, 0x8a, 0x62, 0xf8, 0xd6, 0x67, 0x5c, + 0x2a, 0xe7, 0x0c, 0xd0, 0x9d, 0x2c, 0x00, 0x9b, 0x23, 0xc9, 0x49, 0x93, 0x79, 0xf2, 0x41, 0xa5, + 0xc9, 0xbc, 0xc1, 0xe4, 0x98, 0x34, 0x72, 0x59, 0x5c, 0xd8, 0x6e, 0x96, 0xac, 0x94, 0x89, 0x2a, + 0x49, 0x56, 0xe7, 0x87, 0xbe, 0xe0, 0xc0, 0xb8, 0xb4, 0xcb, 0x44, 0x10, 0x2b, 0x16, 0x79, 0x7e, + 0x36, 0xcd, 0x41, 0x96, 0x28, 0xbe, 0x9e, 0xe1, 0x83, 0x3b, 0x38, 0x53, 0xa9, 0xae, 0xd2, 0xaa, + 0x6a, 0x31, 0x4b, 0x67, 0x15, 0x3a, 0xcc, 0x74, 0x0a, 0xc6, 0x3a, 0x0e, 0xfa, 0xa6, 0xfa, 0x4a, + 0xf8, 0x33, 0x4c, 0xa0, 0xbf, 0x64, 0x59, 0x37, 0xb5, 0xf1, 0xa9, 0x70, 0xf4, 0x25, 0x07, 0xc6, + 0x77, 0x32, 0x0e, 0x0d, 0x91, 0xe8, 0x88, 0xed, 0xbb, 0x4a, 0xf8, 0x72, 0x67, 0xa1, 0xb8, 0x63, + 0x04, 0xe8, 0x36, 0x80, 0xa7, 0x1c, 0xdd, 0x22, 0x21, 0x72, 0xd9, 0x66, 0xf0, 0x80, 0x5f, 0xd5, + 0x4a, 0x7f, 0x63, 0x8d, 0xdf, 0x7d, 0xe7, 0x38, 0xbc, 0xad, 0x3e, 0xc0, 0xfe, 0x9f, 0x4f, 0xc3, + 0xa8, 0x19, 0x9f, 0x42, 0xef, 0x32, 0xcb, 0xe8, 0x5f, 0xc8, 0x56, 0x24, 0x1f, 0x91, 0xf8, 0x46, + 0x55, 0x72, 0xa3, 0x6c, 0x78, 0xe1, 0x58, 0xcb, 0x86, 0xf7, 0x9c, 0x4c, 0xd9, 0xf0, 0xf1, 0xe3, + 0x28, 0x1b, 0x7e, 0xea, 0x48, 0x65, 0xc3, 0xb5, 0xb2, 0xed, 0xbd, 0x77, 0x29, 0xdb, 0x3e, 0x0d, + 0x63, 0xf2, 0xfe, 0x0a, 0x11, 0xf5, 0xa0, 0x79, 0xe8, 0xfa, 0xbc, 0xe8, 0x32, 0x36, 0x6b, 0x36, + 0xe3, 0x2c, 0x3e, 0xfa, 0xbc, 0x03, 0xc5, 0x80, 0xf5, 0xec, 0xb3, 0xf5, 0x0d, 0x15, 0x73, 0x6b, + 0x31, 0x83, 0x59, 0x08, 0x25, 0x99, 0xb1, 0x5b, 0x64, 0xb0, 0x3b, 0xf2, 0x1f, 0xcc, 0x47, 0x80, + 0x5e, 0x81, 0x52, 0xb8, 0xb9, 0xd9, 0x08, 0xbd, 0x6a, 0x5a, 0xdb, 0x5c, 0xc6, 0xd6, 0xf9, 0xfd, + 0x43, 0x55, 0x80, 0x73, 0xb5, 0x0b, 0x1e, 0xee, 0x4a, 0x01, 0x7d, 0x87, 0xaa, 0x22, 0x49, 0x18, + 0x91, 0x6a, 0xea, 0x9d, 0x19, 0x64, 0x73, 0x26, 0xd6, 0xe7, 0x5c, 0x36, 0xf9, 0xf0, 0xd9, 0xab, + 0x87, 0x92, 0x69, 0xc5, 0xd9, 0x61, 0xa1, 0x08, 0xce, 0xb5, 0xf2, 0x9c, 0x43, 0xb1, 0xb8, 0x75, + 0x73, 0x90, 0x8b, 0x4a, 0xbe, 0xba, 0xe7, 0x72, 0xdd, 0x4b, 0x31, 0xee, 0x42, 0x59, 0xaf, 0x7a, + 0x3e, 0x70, 0x32, 0x55, 0xcf, 0x3f, 0x0e, 0x50, 0x91, 0x25, 0xa4, 0xa4, 0xbb, 0x61, 0xc9, 0xca, + 0x75, 0x10, 0x4e, 0x53, 0xfb, 0xc4, 0xa2, 0x62, 0x83, 0x35, 0x96, 0xe8, 0x7f, 0xe7, 0x16, 0xe8, + 0xe7, 0x3e, 0x95, 0x9a, 0xf5, 0x3d, 0xf1, 0xb6, 0x2b, 0xd2, 0xff, 0xf7, 0x1d, 0x98, 0xe0, 0x3b, + 0x2f, 0xab, 0xce, 0x53, 0x65, 0x42, 0xdc, 0x4f, 0xb1, 0x9d, 0x7e, 0xc1, 0x32, 0xd1, 0xca, 0x06, + 0x57, 0x16, 0xac, 0x3d, 0x60, 0x24, 0xe8, 0x2b, 0x39, 0x46, 0xc4, 0x98, 0x2d, 0x2f, 0x65, 0x7e, + 0x71, 0xf7, 0xd3, 0xfb, 0x87, 0xb1, 0x1b, 0xfe, 0x71, 0x57, 0x27, 0x2a, 0x62, 0xc3, 0xfb, 0x2b, + 0xc7, 0xe4, 0x44, 0xd5, 0x2b, 0xd0, 0x1f, 0xc9, 0x95, 0xfa, 0x45, 0x07, 0xc6, 0xbd, 0x4c, 0xba, + 0x04, 0xf3, 0xfc, 0x58, 0xf1, 0x42, 0x4d, 0x47, 0x69, 0x0e, 0x06, 0x53, 0xeb, 0xb2, 0x99, 0x19, + 0xb8, 0x83, 0xf9, 0xc4, 0x67, 0x1c, 0xfe, 0xd9, 0x9a, 0xae, 0x7a, 0xd1, 0x86, 0xa9, 0x17, 0x2d, + 0xdb, 0xfc, 0x70, 0x86, 0xae, 0xa0, 0xfd, 0xaa, 0x03, 0x67, 0xf2, 0xc4, 0x76, 0xce, 0x90, 0x3e, + 0x62, 0x0e, 0xc9, 0xa2, 0xf1, 0xa1, 0x0f, 0xc8, 0xce, 0xd7, 0x02, 0xfe, 0x68, 0x50, 0x0b, 0xa6, + 0x25, 0xa4, 0x65, 0x3d, 0xb9, 0x36, 0x80, 0x3e, 0x3f, 0x68, 0xf8, 0x01, 0x11, 0x17, 0xe9, 0x6c, + 0x9a, 0x62, 0xe2, 0xeb, 0x1c, 0x94, 0x3a, 0x16, 0x5c, 0x1e, 0x70, 0x6c, 0x2d, 0xfb, 0xe5, 0xa1, + 0xde, 0x93, 0xff, 0xf2, 0xd0, 0x0e, 0x0c, 0xee, 0xf8, 0x49, 0x9d, 0xe5, 0x04, 0x88, 0x90, 0x95, + 0x85, 0x0b, 0x68, 0x94, 0x5c, 0x3a, 0xf7, 0x9b, 0x92, 0x01, 0x4e, 0x79, 0xa1, 0x8b, 0x9c, 0x31, + 0x4b, 0xa9, 0xcd, 0xe6, 0x3a, 0xde, 0x94, 0x0d, 0x38, 0xc5, 0xa1, 0x8b, 0x35, 0x4c, 0x7f, 0xc9, + 0x42, 0x33, 0xa2, 0x86, 0xa9, 0x8d, 0xda, 0x74, 0x82, 0x22, 0xbf, 0xe6, 0x79, 0x53, 0xe3, 0x81, + 0x0d, 0x8e, 0xaa, 0x8c, 0xec, 0x40, 0xd7, 0x32, 0xb2, 0xb7, 0x99, 0x16, 0x92, 0xf8, 0x41, 0x9b, + 0xac, 0x06, 0x22, 0x11, 0x77, 0xd9, 0xce, 0xa5, 0x54, 0x4e, 0x93, 0xdb, 0x95, 0xe9, 0x6f, 0xac, + 0xf1, 0xd3, 0x22, 0x07, 0x43, 0x07, 0x46, 0x0e, 0x52, 0xcf, 0xc1, 0xb0, 0x75, 0xcf, 0x41, 0x42, + 0x5a, 0x56, 0x3c, 0x07, 0x6f, 0x2b, 0x1b, 0xf7, 0x4f, 0x1d, 0x40, 0x4a, 0x99, 0xf0, 0xe2, 0x2d, + 0xf1, 0xb9, 0xb8, 0xe3, 0xcf, 0x76, 0xfb, 0x84, 0x03, 0x10, 0xa8, 0xef, 0xd3, 0xd9, 0x3d, 0xb5, + 0x38, 0xcd, 0x74, 0x00, 0x29, 0x0c, 0x6b, 0x3c, 0xdd, 0xff, 0xee, 0xa4, 0x49, 0xa5, 0xe9, 0xdc, + 0x4f, 0x20, 0x17, 0x6a, 0xd7, 0xcc, 0x85, 0x5a, 0xb7, 0xe8, 0x81, 0x56, 0xd3, 0xe8, 0x92, 0x15, + 0xf5, 0xd3, 0x02, 0x8c, 0xe9, 0xc8, 0x65, 0x72, 0x12, 0x0f, 0x7b, 0xc7, 0x48, 0x6d, 0xbc, 0x6e, + 0x77, 0xbe, 0x65, 0x11, 0xc8, 0xc8, 0x4b, 0xa3, 0xfd, 0x78, 0x26, 0x8d, 0xf6, 0xa6, 0x7d, 0xd6, + 0x07, 0xe7, 0xd2, 0xfe, 0x57, 0x07, 0x4e, 0x67, 0x7a, 0x9c, 0xc0, 0x06, 0xdb, 0x36, 0x37, 0xd8, + 0x8b, 0xd6, 0x67, 0xdd, 0x65, 0x77, 0x7d, 0xab, 0xd0, 0x31, 0x5b, 0x66, 0x99, 0x7c, 0xda, 0x81, + 0x62, 0xe2, 0xc5, 0x5b, 0x32, 0x2d, 0xe9, 0x23, 0xc7, 0xb2, 0x03, 0xa6, 0xe8, 0xff, 0x42, 0x3a, + 0xab, 0xf1, 0x31, 0x18, 0xe6, 0xdc, 0x27, 0x3e, 0xe5, 0x00, 0xa4, 0x48, 0x0f, 0x4a, 0x65, 0x75, + 0xbf, 0x5b, 0x80, 0xb3, 0xb9, 0xdb, 0x08, 0x7d, 0x56, 0xb9, 0x99, 0x1c, 0xdb, 0x49, 0x77, 0x06, + 0x23, 0xdd, 0xdb, 0x34, 0x62, 0x78, 0x9b, 0x84, 0x93, 0xe9, 0x41, 0x19, 0x1c, 0x42, 0x4c, 0x6b, + 0x8b, 0xf5, 0x13, 0x27, 0xcd, 0xe3, 0x54, 0x05, 0x67, 0xfe, 0x0c, 0xde, 0xae, 0x70, 0x7f, 0xaa, + 0xa5, 0x9e, 0xcb, 0x89, 0x9e, 0x80, 0xac, 0xd8, 0x31, 0x65, 0x05, 0xb6, 0x1f, 0x0e, 0xed, 0x22, + 0x2c, 0x3e, 0x0a, 0x79, 0xf1, 0xd1, 0xc3, 0x55, 0xab, 0x33, 0xee, 0x29, 0x16, 0x0e, 0x7d, 0x4f, + 0x71, 0x04, 0x86, 0x5e, 0xf6, 0x5b, 0x2a, 0x94, 0x37, 0xf5, 0xfd, 0x1f, 0x5f, 0x78, 0xe8, 0x07, + 0x3f, 0xbe, 0xf0, 0xd0, 0x8f, 0x7e, 0x7c, 0xe1, 0xa1, 0x4f, 0xec, 0x5f, 0x70, 0xbe, 0xbf, 0x7f, + 0xc1, 0xf9, 0xc1, 0xfe, 0x05, 0xe7, 0x47, 0xfb, 0x17, 0x9c, 0x7f, 0xbf, 0x7f, 0xc1, 0xf9, 0x1b, + 0xff, 0xe1, 0xc2, 0x43, 0x2f, 0x0f, 0xc8, 0x89, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, + 0x90, 0xd4, 0xab, 0x3d, 0xd0, 0x00, 0x00, } func (m *Amount) Marshal() (dAtA []byte, err error) { @@ -10679,6 +10681,13 @@ func (m *SemaphoreRef) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.RebalanceKey != nil { + i -= len(*m.RebalanceKey) + copy(dAtA[i:], *m.RebalanceKey) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.RebalanceKey))) + i-- + dAtA[i] = 0x12 + } if m.ConfigMapKeyRef != nil { { size, err := m.ConfigMapKeyRef.MarshalToSizedBuffer(dAtA[:i]) @@ -15844,6 +15853,10 @@ func (m *SemaphoreRef) Size() (n int) { l = m.ConfigMapKeyRef.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.RebalanceKey != nil { + l = len(*m.RebalanceKey) + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -18438,6 +18451,7 @@ func (this *SemaphoreRef) String() string { } s := strings.Join([]string{`&SemaphoreRef{`, `ConfigMapKeyRef:` + strings.Replace(fmt.Sprintf("%v", this.ConfigMapKeyRef), "ConfigMapKeySelector", "v1.ConfigMapKeySelector", 1) + `,`, + `RebalanceKey:` + valueToStringGenerated(this.RebalanceKey) + `,`, `}`, }, "") return s @@ -36777,6 +36791,39 @@ func (m *SemaphoreRef) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RebalanceKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.RebalanceKey = &s + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/pkg/apis/workflow/v1alpha1/generated.proto b/pkg/apis/workflow/v1alpha1/generated.proto index 5d28c7f787b5..09e604f22e3b 100644 --- a/pkg/apis/workflow/v1alpha1/generated.proto +++ b/pkg/apis/workflow/v1alpha1/generated.proto @@ -1400,6 +1400,9 @@ message SemaphoreHolding { message SemaphoreRef { // ConfigMapKeyRef is configmap selector for Semaphore configuration optional k8s.io.api.core.v1.ConfigMapKeySelector configMapKeyRef = 1; + + // RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key + optional string rebalanceKey = 2; } message SemaphoreStatus { diff --git a/pkg/apis/workflow/v1alpha1/openapi_generated.go b/pkg/apis/workflow/v1alpha1/openapi_generated.go index 0f08cbea9f72..d172b1ce4893 100644 --- a/pkg/apis/workflow/v1alpha1/openapi_generated.go +++ b/pkg/apis/workflow/v1alpha1/openapi_generated.go @@ -5572,6 +5572,13 @@ func schema_pkg_apis_workflow_v1alpha1_SemaphoreRef(ref common.ReferenceCallback Ref: ref("k8s.io/api/core/v1.ConfigMapKeySelector"), }, }, + "rebalanceKey": { + SchemaProps: spec.SchemaProps{ + Description: "RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, diff --git a/pkg/apis/workflow/v1alpha1/workflow_types.go b/pkg/apis/workflow/v1alpha1/workflow_types.go index 7566636cf932..574003b5f518 100644 --- a/pkg/apis/workflow/v1alpha1/workflow_types.go +++ b/pkg/apis/workflow/v1alpha1/workflow_types.go @@ -1633,6 +1633,8 @@ func (s *Synchronization) GetType() SynchronizationType { type SemaphoreRef struct { // ConfigMapKeyRef is configmap selector for Semaphore configuration ConfigMapKeyRef *apiv1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty" protobuf:"bytes,1,opt,name=configMapKeyRef"` + // RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key + RebalanceKey *string `json:"rebalanceKey,omitempty" protobuf:"bytes,2,opt,name=rebalanceKey"` } // Mutex holds Mutex configuration diff --git a/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go index 307377046b2b..9cf726c072db 100644 --- a/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/workflow/v1alpha1/zz_generated.deepcopy.go @@ -2825,6 +2825,11 @@ func (in *SemaphoreRef) DeepCopyInto(out *SemaphoreRef) { *out = new(v1.ConfigMapKeySelector) (*in).DeepCopyInto(*out) } + if in.RebalanceKey != nil { + in, out := &in.RebalanceKey, &out.RebalanceKey + *out = new(string) + **out = **in + } return } diff --git a/pkg/plugins/executor/swagger.yml b/pkg/plugins/executor/swagger.yml index 56a198fb2471..39ef712b00e0 100644 --- a/pkg/plugins/executor/swagger.yml +++ b/pkg/plugins/executor/swagger.yml @@ -3816,6 +3816,10 @@ definitions: properties: configMapKeyRef: $ref: '#/definitions/ConfigMapKeySelector' + rebalanceKey: + description: RebalanceKey gives an equal share of locks to all resources that + specify the same rebalance key + type: string type: object Sequence: description: Sequence expands a workflow step into numeric range diff --git a/sdks/java/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md b/sdks/java/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md index 1b8ee395bd1d..f87abc1285a9 100644 --- a/sdks/java/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md +++ b/sdks/java/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md @@ -9,6 +9,7 @@ SemaphoreRef is a reference of Semaphore Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **configMapKeyRef** | [**io.kubernetes.client.openapi.models.V1ConfigMapKeySelector**](io.kubernetes.client.openapi.models.V1ConfigMapKeySelector.md) | | [optional] +**rebalanceKey** | **String** | RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key | [optional] diff --git a/sdks/python/client/argo_workflows/model/io_argoproj_workflow_v1alpha1_semaphore_ref.py b/sdks/python/client/argo_workflows/model/io_argoproj_workflow_v1alpha1_semaphore_ref.py index 562b1788fb84..ec6cef675891 100644 --- a/sdks/python/client/argo_workflows/model/io_argoproj_workflow_v1alpha1_semaphore_ref.py +++ b/sdks/python/client/argo_workflows/model/io_argoproj_workflow_v1alpha1_semaphore_ref.py @@ -88,6 +88,7 @@ def openapi_types(): lazy_import() return { 'config_map_key_ref': (ConfigMapKeySelector,), # noqa: E501 + 'rebalance_key': (str,), # noqa: E501 } @cached_property @@ -97,6 +98,7 @@ def discriminator(): attribute_map = { 'config_map_key_ref': 'configMapKeyRef', # noqa: E501 + 'rebalance_key': 'rebalanceKey', # noqa: E501 } read_only_vars = { @@ -141,6 +143,7 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) config_map_key_ref (ConfigMapKeySelector): [optional] # noqa: E501 + rebalance_key (str): RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key. [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) @@ -223,6 +226,7 @@ def __init__(self, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) config_map_key_ref (ConfigMapKeySelector): [optional] # noqa: E501 + rebalance_key (str): RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key. [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) diff --git a/sdks/python/client/docs/ClusterWorkflowTemplateServiceApi.md b/sdks/python/client/docs/ClusterWorkflowTemplateServiceApi.md index 9f3cd8d10c29..09559ce08d9c 100644 --- a/sdks/python/client/docs/ClusterWorkflowTemplateServiceApi.md +++ b/sdks/python/client/docs/ClusterWorkflowTemplateServiceApi.md @@ -1046,6 +1046,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -5173,6 +5174,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -9683,6 +9685,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -11846,6 +11849,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -15973,6 +15977,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -20483,6 +20488,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -22550,6 +22556,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -26677,6 +26684,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -31187,6 +31195,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", diff --git a/sdks/python/client/docs/CronWorkflowServiceApi.md b/sdks/python/client/docs/CronWorkflowServiceApi.md index b7270215efb5..a54699c37ffc 100644 --- a/sdks/python/client/docs/CronWorkflowServiceApi.md +++ b/sdks/python/client/docs/CronWorkflowServiceApi.md @@ -1100,6 +1100,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -5227,6 +5228,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -9737,6 +9739,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -11973,6 +11976,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -16100,6 +16104,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -20610,6 +20615,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -22931,6 +22937,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -27058,6 +27065,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -31568,6 +31576,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", diff --git a/sdks/python/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md b/sdks/python/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md index b945b2aadeee..4bbbb61a80e0 100644 --- a/sdks/python/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md +++ b/sdks/python/client/docs/IoArgoprojWorkflowV1alpha1SemaphoreRef.md @@ -6,6 +6,7 @@ SemaphoreRef is a reference of Semaphore Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **config_map_key_ref** | [**ConfigMapKeySelector**](ConfigMapKeySelector.md) | | [optional] +**rebalance_key** | **str** | RebalanceKey gives an equal share of locks to all resources that specify the same rebalance key | [optional] **any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/python/client/docs/WorkflowServiceApi.md b/sdks/python/client/docs/WorkflowServiceApi.md index 1843670077bf..247f045e38ea 100644 --- a/sdks/python/client/docs/WorkflowServiceApi.md +++ b/sdks/python/client/docs/WorkflowServiceApi.md @@ -1061,6 +1061,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -5188,6 +5189,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -9698,6 +9700,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -16092,6 +16095,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -17419,6 +17423,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -21546,6 +21551,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -26056,6 +26062,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -28258,6 +28265,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -32385,6 +32393,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -36895,6 +36904,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -43289,6 +43299,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -44616,6 +44627,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -48743,6 +48755,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -53253,6 +53266,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", diff --git a/sdks/python/client/docs/WorkflowTemplateServiceApi.md b/sdks/python/client/docs/WorkflowTemplateServiceApi.md index 3aeb2bad2907..950cf271bc45 100644 --- a/sdks/python/client/docs/WorkflowTemplateServiceApi.md +++ b/sdks/python/client/docs/WorkflowTemplateServiceApi.md @@ -1048,6 +1048,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -5175,6 +5176,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -9685,6 +9687,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -11855,6 +11858,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -15982,6 +15986,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -20492,6 +20497,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -22571,6 +22577,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), template_defaults=IoArgoprojWorkflowV1alpha1Template( @@ -26698,6 +26705,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", @@ -31208,6 +31216,7 @@ with argo_workflows.ApiClient(configuration) as api_client: name="name_example", optional=True, ), + rebalance_key="rebalance_key_example", ), ), timeout="timeout_example", diff --git a/workflow/controller/controller.go b/workflow/controller/controller.go index 37d4e6e733dc..fd87dc0b8fc5 100644 --- a/workflow/controller/controller.go +++ b/workflow/controller/controller.go @@ -341,6 +341,33 @@ func (wfc *WorkflowController) createSynchronizationManager(ctx context.Context) return strconv.Atoi(value) } + getSemaphoreStrategy := func(lockKey string) (config.SemaphoreStrategy, error) { + lockName, err := sync.DecodeLockName(lockKey) + if err != nil { + return config.SemaphoreStrategyDefault, err + } + configMap, err := wfc.kubeclientset.CoreV1().ConfigMaps(lockName.Namespace).Get(ctx, lockName.ResourceName, metav1.GetOptions{}) + if err != nil { + return config.SemaphoreStrategyDefault, err + } + + // we chose to make *-strategy a reserved pattern because the alternatives seemed like they would require reconfiguring quite + // a few things, down to the way in which semaphore names are defined. Notice that in initializeSemaphore we pass along the + // held semaphore's name from the Workflow itself - it doesn't seem like the right moment to go about changing those mechanics. + value, found := configMap.Data[fmt.Sprintf("%s-strategy", lockName.Key)] + if !found { + return config.SemaphoreStrategyDefault, nil + } + + if value == string(config.SemaphoreStrategyDefault) { + return config.SemaphoreStrategyDefault, nil + } else if value == string(config.SemaphoreStrategyRebalanced) { + return config.SemaphoreStrategyRebalanced, nil + } else { + return config.SemaphoreStrategyDefault, fmt.Errorf("unknown semaphore strategy '%s' for lock '%s'", value, lockName) + } + } + nextWorkflow := func(key string) { wfc.wfQueue.AddAfter(key, semaphoreNotifyDelay) } @@ -354,7 +381,7 @@ func (wfc *WorkflowController) createSynchronizationManager(ctx context.Context) return exists } - wfc.syncManager = sync.NewLockManager(getSyncLimit, nextWorkflow, isWFDeleted) + wfc.syncManager = sync.NewLockManager(getSyncLimit, getSemaphoreStrategy, nextWorkflow, isWFDeleted) } // list all running workflows to initialize throttler and syncManager diff --git a/workflow/controller/operator_concurrency_test.go b/workflow/controller/operator_concurrency_test.go index 66f4940b4727..a55ea026ad39 100644 --- a/workflow/controller/operator_concurrency_test.go +++ b/workflow/controller/operator_concurrency_test.go @@ -13,6 +13,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + "github.com/argoproj/argo-workflows/v3/config" argoErr "github.com/argoproj/argo-workflows/v3/errors" wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "github.com/argoproj/argo-workflows/v3/workflow/sync" @@ -103,6 +104,10 @@ spec: name: workflow-controller-configmap1 ` +var getSemaphoreQueueTypeAlwaysDefault = func(s string) (config.SemaphoreStrategy, error) { + return config.SemaphoreStrategyDefault, nil +} + var workflowExistenceFunc = func(key string) bool { return true } @@ -133,7 +138,7 @@ func TestSemaphoreTmplLevel(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -194,7 +199,7 @@ func TestSemaphoreScriptTmplLevel(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -254,7 +259,7 @@ func TestSemaphoreResourceTmplLevel(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -316,7 +321,7 @@ func TestSemaphoreWithOutConfigMap(t *testing.T) { defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) t.Run("SemaphoreRefWithOutConfigMap", func(t *testing.T) { @@ -372,7 +377,7 @@ func TestMutexInDAG(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) t.Run("MutexWithDAG", func(t *testing.T) { wf := wfv1.MustUnmarshalWorkflow(DAGWithMutex) @@ -444,8 +449,11 @@ func TestMutexInDAGWithInterpolation(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { - }, workflowExistenceFunc) + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), + func(s string) (config.SemaphoreStrategy, error) { + return config.SemaphoreStrategyDefault, nil + }, func(key string) { + }, workflowExistenceFunc) t.Run("InterpolatedMutexWithDAG", func(t *testing.T) { wf := wfv1.MustUnmarshalWorkflow(DAGWithInterpolatedMutex) wf, err := controller.wfclientset.ArgoprojV1alpha1().Workflows(wf.Namespace).Create(ctx, wf, metav1.CreateOptions{}) @@ -509,7 +517,7 @@ func TestSynchronizationWithRetry(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -717,7 +725,7 @@ func TestSynchronizationWithStep(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -794,7 +802,7 @@ func TestSynchronizationWithStepRetry(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) var cm v1.ConfigMap wfv1.MustUnmarshal([]byte(configMap), &cm) @@ -858,7 +866,7 @@ func TestSynchronizationForPendingShuttingdownWfs(t *testing.T) { cancel, controller := newController() defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) t.Run("PendingShuttingdownTerminatingWf", func(t *testing.T) { diff --git a/workflow/controller/operator_test.go b/workflow/controller/operator_test.go index 575d72240a44..b838f6e52223 100644 --- a/workflow/controller/operator_test.go +++ b/workflow/controller/operator_test.go @@ -7349,7 +7349,7 @@ func TestMutexWfPendingWithNoPod(t *testing.T) { cancel, controller := newController(wf) defer cancel() ctx := context.Background() - controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), func(key string) { + controller.syncManager = sync.NewLockManager(GetSyncLimitFunc(ctx, controller.kubeclientset), getSemaphoreQueueTypeAlwaysDefault, func(key string) { }, workflowExistenceFunc) _, _, _, err := controller.syncManager.TryAcquire(wf, "test", &wfv1.Synchronization{Mutex: &wfv1.Mutex{Name: "welcome"}}) assert.NoError(t, err) diff --git a/workflow/sync/common.go b/workflow/sync/common.go index b4a19e9c5c84..e8a2f95325ea 100644 --- a/workflow/sync/common.go +++ b/workflow/sync/common.go @@ -1,12 +1,16 @@ package sync -import "time" +import ( + "time" + + wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" +) type Semaphore interface { acquire(holderKey string) bool tryAcquire(holderKey string) (bool, string) release(key string) bool - addToQueue(holderKey string, priority int32, creationTime time.Time) + addToQueue(holderKey string, priority int32, creationTime time.Time, syncLockRef *wfv1.Synchronization) removeFromQueue(holderKey string) getCurrentHolders() []string getCurrentPending() []string @@ -14,3 +18,15 @@ type Semaphore interface { getLimit() int resize(n int) bool } + +// SemaphoreStrategyQueue is aware that it supports a semaphore, and implements a specific +// strategy for maintaining order of pending holders +type SemaphoreStrategyQueue interface { + peek() *item + pop() *item + add(key Key, priority int32, creationTime time.Time, syncLockRef *wfv1.Synchronization) + remove(key Key) + onRelease(key Key) + all() []*item + Len() int +} diff --git a/workflow/sync/mutex.go b/workflow/sync/mutex.go index 7a4749825a48..d67bbfbefdbe 100644 --- a/workflow/sync/mutex.go +++ b/workflow/sync/mutex.go @@ -3,6 +3,8 @@ package sync import ( "sync" "time" + + wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" ) type PriorityMutex struct { @@ -24,7 +26,7 @@ func NewMutex(name string, nextWorkflow NextWorkflow) *PriorityMutex { return &PriorityMutex{ name: name, lock: &sync.Mutex{}, - mutex: NewSemaphore(name, 1, nextWorkflow, "mutex"), + mutex: NewSemaphore(name, 1, nextWorkflow, "mutex", &priorityQueue{itemByKey: make(map[string]*item)}), } } @@ -56,10 +58,10 @@ func (m *PriorityMutex) acquire(holderKey string) bool { return m.mutex.acquire(holderKey) } -func (m *PriorityMutex) addToQueue(holderKey string, priority int32, creationTime time.Time) { +func (m *PriorityMutex) addToQueue(holderKey string, priority int32, creationTime time.Time, syncLockRef *wfv1.Synchronization) { m.lock.Lock() defer m.lock.Unlock() - m.mutex.addToQueue(holderKey, priority, creationTime) + m.mutex.addToQueue(holderKey, priority, creationTime, syncLockRef) } func (m *PriorityMutex) removeFromQueue(holderKey string) { diff --git a/workflow/sync/mutex_test.go b/workflow/sync/mutex_test.go index 5d0111c724e8..44ca03e8c98a 100644 --- a/workflow/sync/mutex_test.go +++ b/workflow/sync/mutex_test.go @@ -93,7 +93,7 @@ func TestMutexLock(t *testing.T) { kube := fake.NewSimpleClientset() syncLimitFunc := GetSyncLimitFunc(kube) t.Run("InitializeSynchronization", func(t *testing.T) { - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(mutexwfstatus) wfclientset := fakewfclientset.NewSimpleClientset(wf) @@ -106,7 +106,7 @@ func TestMutexLock(t *testing.T) { }) t.Run("WfLevelMutexAcquireAndRelease", func(t *testing.T) { var nextWorkflow string - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { nextWorkflow = key }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(mutexWf) @@ -284,7 +284,7 @@ func TestMutexTmplLevel(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("TemplateLevelAcquireAndRelease", func(t *testing.T) { // var nextKey string - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { // nextKey = key }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(mutexWfWithTmplLevel) diff --git a/workflow/sync/rebalanced.go b/workflow/sync/rebalanced.go new file mode 100644 index 000000000000..374ce2bafea3 --- /dev/null +++ b/workflow/sync/rebalanced.go @@ -0,0 +1,144 @@ +package sync + +import ( + "math" + "time" + + wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" +) + +// TODO: maintain cache, expire entries + +// RebalanceQueue implements the rebalance strategy for consumption in Semaphore +type RebalanceQueue struct { + items []*item // standard item with an attached rebalance key + rebalanceKeyCache map[string]string // mapping from resource name (holder) to holder's rebalance key + semaphore Semaphore // reference to parent semaphore, so we can get holders +} + +func NewRebalanceQueue() *RebalanceQueue { + return &RebalanceQueue{ + items: make([]*item, 0), + rebalanceKeyCache: make(map[string]string, 0), + } +} + +// RebalanceQueue needs to reference semaphore to know current lock holders +func (r *RebalanceQueue) setParentSemaphore(s Semaphore) { + r.semaphore = s +} + +// determines the best ordering based on currently-outstanding keys +func (r *RebalanceQueue) onRelease(key Key) { + // we need pending + holding counts for rebalance keys, and just holding counts + allRebalanceKeys := make(map[string]int, 0) + holderRebalanceKeys := make(map[string]int, 0) + + for _, h := range r.semaphore.getCurrentHolders() { + rk := r.rebalanceKeyCache[h] + allRebalanceKeys[rk] += 1 + if h != key { + holderRebalanceKeys[rk] += 1 + } + } + + for _, p := range r.items { + rk := r.rebalanceKeyCache[p.key] + allRebalanceKeys[rk] += 1 + } + + // partition r.queue into items that can / can't be scheduled + can := make([]*item, 0) + overflow := make(map[string]*item, 0) + cant := make([]*item, 0) + + maxLocksPerUserFloor := math.Floor(float64(r.semaphore.getLimit()) / float64(len(allRebalanceKeys))) + // iterate through pending queue to determine what has changed + for _, p := range r.items { + if p.key != key { + rebalanceKey := r.rebalanceKeyCache[p.key] + // we want to ignore "key" since removal from queue happens after release in semaphore + if float64(holderRebalanceKeys[rebalanceKey]) < maxLocksPerUserFloor { + can = append(can, p) + holderRebalanceKeys[rebalanceKey] += 1 + } else { + // don't add to overflow if already maxLocksPerUserFloor + 1 because we run the risk of kicking + // off an extra one! + if overflow[rebalanceKey] == nil && holderRebalanceKeys[rebalanceKey] < int(maxLocksPerUserFloor)+1 { + overflow[rebalanceKey] = p + } else { + cant = append(cant, p) + } + } + } + } + + // fill "can" with earliest submitted items until we reach limit + for len(overflow) > 0 { + var earliest *item + var rebalanceKey string + for k, p := range overflow { + if earliest == nil || earliest.creationTime.Unix() > p.creationTime.Unix() { + earliest = p + rebalanceKey = k + } + } + delete(overflow, rebalanceKey) + can = append(can, earliest) + } + + delete(r.rebalanceKeyCache, key) + + r.items = append(can, cant...) +} + +func (r *RebalanceQueue) peek() *item { + return r.items[0] +} + +func (r *RebalanceQueue) pop() *item { + first := r.items[0] + r.remove(first.key) + return first +} + +// rebalance queues, at the moment, do not support priority +// +// if queue has key, skip +// if queue doesn't, add along with rebalance key +func (r *RebalanceQueue) add(key Key, _ int32, creationTime time.Time, syncLockRef *wfv1.Synchronization) { + found := false + for _, p := range r.items { + if p.key == key { + found = true + } + } + + if !found { + rebalanceKey := "" + if syncLockRef != nil && syncLockRef.Semaphore != nil && syncLockRef.Semaphore.RebalanceKey != nil { + rebalanceKey = *syncLockRef.Semaphore.RebalanceKey + } + + r.rebalanceKeyCache[key] = rebalanceKey + + r.items = append(r.items, &item{key: key, creationTime: creationTime, priority: 1, index: -1}) + } +} + +func (r *RebalanceQueue) remove(key Key) { + for i, p := range r.items { + if p.key == key { + r.items = append(r.items[:i], r.items[i+1:]...) + return + } + } +} + +func (r *RebalanceQueue) Len() int { + return len(r.items) +} + +func (r *RebalanceQueue) all() []*item { + return r.items +} diff --git a/workflow/sync/rebalanced_test.go b/workflow/sync/rebalanced_test.go new file mode 100644 index 000000000000..bffde63a7acc --- /dev/null +++ b/workflow/sync/rebalanced_test.go @@ -0,0 +1,254 @@ +package sync + +import ( + "runtime/debug" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" +) + +func syncWRebalance(key string) *v1alpha1.Synchronization { + return &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{ + RebalanceKey: &key, + }} +} + +func TestSimpleRebalance(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 4, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-001-with-AAA", -1, time.Unix(2, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-002-with-AAA", -1, time.Unix(3, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-003-with-AAA", -1, time.Unix(4, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-004-with-AAA", -1, time.Unix(5, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-005-with-AAA", -1, time.Unix(6, 0), syncWRebalance("AAA")) + + rq.add("argo/wf-000/key-000-with-BBB", -1, time.Unix(7, 0), syncWRebalance("BBB")) + rq.add("argo/wf-000/key-001-with-BBB", -1, time.Unix(8, 0), syncWRebalance("BBB")) + rq.add("argo/wf-000/key-002-with-BBB", -1, time.Unix(9, 0), syncWRebalance("BBB")) + rq.add("argo/wf-000/key-003-with-BBB", -1, time.Unix(10, 0), syncWRebalance("BBB")) + rq.add("argo/wf-000/key-004-with-BBB", -1, time.Unix(11, 0), syncWRebalance("BBB")) + rq.add("argo/wf-000/key-005-with-BBB", -1, time.Unix(12, 0), syncWRebalance("BBB")) + + // important: release is always called before remove in manager + rq.onRelease("argo/wf-000/key-000-with-AAA") + rq.remove("argo/wf-000/key-000-with-AAA") + + assert.Equal(t, rq.all()[0].key, "argo/wf-000/key-001-with-AAA") + assert.Equal(t, rq.all()[1].key, "argo/wf-000/key-002-with-AAA") + assert.Equal(t, rq.all()[2].key, "argo/wf-000/key-000-with-BBB") + assert.Equal(t, rq.all()[3].key, "argo/wf-000/key-001-with-BBB") + // rest of the items don't matter - we will never try to schedule past the limit, and we have no idea + // what resource will finish next, so it'd be a complete guess. reshuffle after the next onRelease +} + +// TestModWithLeftover ensures that if ${ limit / numUniqueRebalanceKeys } is a non-integer, that +// the remaining positions are filled equally (i.e. one user doesn't get an unfair number of locks) +// +// e.g. suppose a limit of 17 and we have 6 distinct rebalance keys. 17 % 6 is 5, and these 5 +// remaining slots should be given to 5 distinct requesters, BUT NEVER to a requester that already +// is holding 3 locks +func TestModWithLeftover(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 17, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-001-with-AAA", -1, time.Unix(2, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-002-with-AAA", -1, time.Unix(3, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-003-with-AAA", -1, time.Unix(4, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-004-with-AAA", -1, time.Unix(5, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-005-with-AAA", -1, time.Unix(6, 0), syncWRebalance("AAA")) + + rq.add("argo/wf-001/key-000-with-BBB", -1, time.Unix(7, 0), syncWRebalance("BBB")) + rq.add("argo/wf-001/key-001-with-BBB", -1, time.Unix(8, 0), syncWRebalance("BBB")) + rq.add("argo/wf-001/key-002-with-BBB", -1, time.Unix(9, 0), syncWRebalance("BBB")) + rq.add("argo/wf-001/key-003-with-BBB", -1, time.Unix(10, 0), syncWRebalance("BBB")) + rq.add("argo/wf-001/key-004-with-BBB", -1, time.Unix(11, 0), syncWRebalance("BBB")) + rq.add("argo/wf-001/key-005-with-BBB", -1, time.Unix(12, 0), syncWRebalance("BBB")) + + rq.add("argo/wf-002/key-000-with-CCC", -1, time.Unix(13, 0), syncWRebalance("CCC")) + rq.add("argo/wf-002/key-001-with-CCC", -1, time.Unix(14, 0), syncWRebalance("CCC")) + rq.add("argo/wf-002/key-002-with-CCC", -1, time.Unix(15, 0), syncWRebalance("CCC")) + rq.add("argo/wf-002/key-003-with-CCC", -1, time.Unix(16, 0), syncWRebalance("CCC")) + rq.add("argo/wf-002/key-004-with-CCC", -1, time.Unix(17, 0), syncWRebalance("CCC")) + rq.add("argo/wf-002/key-005-with-CCC", -1, time.Unix(18, 0), syncWRebalance("CCC")) + + rq.add("argo/wf-003/key-000-with-DDD", -1, time.Unix(19, 0), syncWRebalance("DDD")) + rq.add("argo/wf-003/key-001-with-DDD", -1, time.Unix(20, 0), syncWRebalance("DDD")) + rq.add("argo/wf-003/key-002-with-DDD", -1, time.Unix(21, 0), syncWRebalance("DDD")) + rq.add("argo/wf-003/key-003-with-DDD", -1, time.Unix(22, 0), syncWRebalance("DDD")) + rq.add("argo/wf-003/key-004-with-DDD", -1, time.Unix(23, 0), syncWRebalance("DDD")) + rq.add("argo/wf-003/key-005-with-DDD", -1, time.Unix(24, 0), syncWRebalance("DDD")) + + rq.add("argo/wf-004/key-000-with-EEE", -1, time.Unix(25, 0), syncWRebalance("EEE")) + rq.add("argo/wf-004/key-001-with-EEE", -1, time.Unix(26, 0), syncWRebalance("EEE")) + rq.add("argo/wf-004/key-002-with-EEE", -1, time.Unix(27, 0), syncWRebalance("EEE")) + rq.add("argo/wf-004/key-003-with-EEE", -1, time.Unix(28, 0), syncWRebalance("EEE")) + rq.add("argo/wf-004/key-004-with-EEE", -1, time.Unix(29, 0), syncWRebalance("EEE")) + rq.add("argo/wf-004/key-005-with-EEE", -1, time.Unix(30, 0), syncWRebalance("EEE")) + + rq.add("argo/wf-005/key-000-with-FFF", -1, time.Unix(31, 0), syncWRebalance("FFF")) + rq.add("argo/wf-005/key-001-with-FFF", -1, time.Unix(32, 0), syncWRebalance("FFF")) + rq.add("argo/wf-005/key-002-with-FFF", -1, time.Unix(33, 0), syncWRebalance("FFF")) + rq.add("argo/wf-005/key-003-with-FFF", -1, time.Unix(34, 0), syncWRebalance("FFF")) + rq.add("argo/wf-005/key-004-with-FFF", -1, time.Unix(35, 0), syncWRebalance("FFF")) + rq.add("argo/wf-005/key-005-with-FFF", -1, time.Unix(36, 0), syncWRebalance("FFF")) + + status, msg := s.tryAcquire("argo/wf-000/key-000-with-AAA") + assert.True(t, status) + assert.Empty(t, msg) + // important: release is always called before remove in manager + s.release("argo/wf-000/key-000-with-AAA") + s.removeFromQueue("argo/wf-000/key-000-with-AAA") + + assert.Equal(t, rq.all()[0].key, "argo/wf-000/key-001-with-AAA") + assert.Equal(t, rq.all()[1].key, "argo/wf-000/key-002-with-AAA") + assert.Equal(t, rq.all()[2].key, "argo/wf-001/key-000-with-BBB") + assert.Equal(t, rq.all()[3].key, "argo/wf-001/key-001-with-BBB") + assert.Equal(t, rq.all()[4].key, "argo/wf-002/key-000-with-CCC") + assert.Equal(t, rq.all()[5].key, "argo/wf-002/key-001-with-CCC") + assert.Equal(t, rq.all()[6].key, "argo/wf-003/key-000-with-DDD") + assert.Equal(t, rq.all()[7].key, "argo/wf-003/key-001-with-DDD") + assert.Equal(t, rq.all()[8].key, "argo/wf-004/key-000-with-EEE") + assert.Equal(t, rq.all()[9].key, "argo/wf-004/key-001-with-EEE") + assert.Equal(t, rq.all()[10].key, "argo/wf-005/key-000-with-FFF") + assert.Equal(t, rq.all()[11].key, "argo/wf-005/key-001-with-FFF") + // distribute the remainder, choosing oldest first + assert.Equal(t, rq.all()[12].key, "argo/wf-000/key-003-with-AAA") + assert.Equal(t, rq.all()[13].key, "argo/wf-001/key-002-with-BBB") + assert.Equal(t, rq.all()[14].key, "argo/wf-002/key-002-with-CCC") + assert.Equal(t, rq.all()[15].key, "argo/wf-003/key-002-with-DDD") + assert.Equal(t, rq.all()[16].key, "argo/wf-004/key-002-with-EEE") + // rest of the items don't matter - we will never try to schedule past the limit, and we have no idea + // what resource will finish next, so it'd be a complete guess. reshuffle after the next onRelease + + status, msg = s.tryAcquire("argo/wf-000/key-001-with-AAA") + assert.True(t, status) + assert.Empty(t, msg) + + status, msg = s.tryAcquire("argo/wf-000/key-002-with-AAA") + assert.True(t, status) + assert.Empty(t, msg) + + // technically it's allowed to acquire, but only once we get to overflow. + status, msg = s.tryAcquire("argo/wf-000/key-003-with-AAA") + assert.False(t, status) + assert.Contains(t, msg, "Waiting for test-semaphore lock. Lock status: 15/17") + + // acquire the remaining ones. skip validating output because end of this test will fail if + // something went wrong. + s.tryAcquire("argo/wf-001/key-000-with-BBB") + s.tryAcquire("argo/wf-001/key-001-with-BBB") + s.tryAcquire("argo/wf-002/key-000-with-CCC") + s.tryAcquire("argo/wf-002/key-001-with-CCC") + s.tryAcquire("argo/wf-003/key-000-with-DDD") + s.tryAcquire("argo/wf-003/key-001-with-DDD") + s.tryAcquire("argo/wf-004/key-000-with-EEE") + s.tryAcquire("argo/wf-004/key-001-with-EEE") + s.tryAcquire("argo/wf-005/key-000-with-FFF") + s.tryAcquire("argo/wf-005/key-001-with-FFF") + + // NOW we can acquire the 3rd, "overflow" item + status, msg = s.tryAcquire("argo/wf-000/key-003-with-AAA") + assert.True(t, status) + assert.Empty(t, msg) + + // something other than A finishes + s.release("argo/wf-001/key-001-with-BBB") + s.removeFromQueue("argo/wf-001/key-001-with-BBB") + + // this piece is really important. AAA is holding 3 locks already, which is already in "overflow" (since 17 / 6 + // allows for requesters to have up to 3 locks). If AAA somehow sneaks back into overflow, we'd be in a situation + // where it starts acquiring locks greedily and exceeds this number. We have to keep A out of overflow until one of + // its current locks frees up + assert.Equal(t, rq.all()[0].key, "argo/wf-001/key-002-with-BBB") + assert.Equal(t, rq.all()[1].key, "argo/wf-001/key-003-with-BBB") + assert.Equal(t, rq.all()[2].key, "argo/wf-002/key-002-with-CCC") + assert.Equal(t, rq.all()[3].key, "argo/wf-003/key-002-with-DDD") + assert.Equal(t, rq.all()[4].key, "argo/wf-004/key-002-with-EEE") + assert.Equal(t, rq.all()[5].key, "argo/wf-005/key-002-with-FFF") + + // 12 locks currently being held + assert.Len(t, s.getCurrentHolders(), 12) +} + +// TestDuplicateKey ensures that non-unique lock contenders can only exist once +// in the queue +func TestDuplicateKey(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 4, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(2, 0), syncWRebalance("AAA")) + + assert.Len(t, rq.all(), 1) +} + +// TestFailureToSetParentReference ensures that failure to set parent semaphore does NOT fail gracefully +// (If this test fails, it indicates that an error has been introduced into argo codebase) +func TestFailureToSetParentReference(t *testing.T) { + debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(false) // don't think it's required but feel better doing it + defer func() { + if r := recover(); r == nil { + t.Errorf("The code did not panic") + } + }() + + rq := NewRebalanceQueue() + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + + rq.onRelease("argo/wf-000/key-000-with-AAA") +} + +// TestKeyCacheRemoval ensures that releasing a resource key removes it from in-memory cache +func TestKeyCacheRemoval(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 4, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + rq.onRelease("argo/wf-000/key-000-with-AAA") + +} + +// TestEmptyRebalanceKey ensures that a resource vying for a lock that has forgotten to pass +// a rebalance key (or has not on purpose) will be exist in the same grouping +func TestEmptyRebalanceKey(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 4, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-no-rebalance-key", -1, time.Unix(1, 0), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{ + RebalanceKey: nil, + }}) + + assert.Len(t, rq.all(), 1) + assert.Equal(t, rq.rebalanceKeyCache["argo/wf-000/key-000-no-rebalance-key"], "") +} + +// TestRemove ensures that remove removes item from queue, but does not remove key from cache +func TestRemove(t *testing.T) { + rq := NewRebalanceQueue() + s := NewSemaphore("test-semaphore", 4, func(string) {}, "semaphore", rq) + // rebalance needs a reference to semaphore + rq.setParentSemaphore(s) + + rq.add("argo/wf-000/key-000-with-AAA", -1, time.Unix(1, 0), syncWRebalance("AAA")) + rq.remove("argo/wf-000/key-000-with-AAA") + + assert.Len(t, rq.all(), 0) +} diff --git a/workflow/sync/semaphore.go b/workflow/sync/semaphore.go index 63be7239ddeb..219ce8e5f9f1 100644 --- a/workflow/sync/semaphore.go +++ b/workflow/sync/semaphore.go @@ -8,12 +8,14 @@ import ( log "github.com/sirupsen/logrus" sema "golang.org/x/sync/semaphore" + + wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" ) type PrioritySemaphore struct { name string limit int - pending *priorityQueue + pending SemaphoreStrategyQueue semaphore *sema.Weighted lockHolder map[string]bool lock *sync.Mutex @@ -23,11 +25,11 @@ type PrioritySemaphore struct { var _ Semaphore = &PrioritySemaphore{} -func NewSemaphore(name string, limit int, nextWorkflow NextWorkflow, lockType string) *PrioritySemaphore { +func NewSemaphore(name string, limit int, nextWorkflow NextWorkflow, lockType string, strategyQueue SemaphoreStrategyQueue) *PrioritySemaphore { return &PrioritySemaphore{ name: name, limit: limit, - pending: &priorityQueue{itemByKey: make(map[string]*item)}, + pending: strategyQueue, semaphore: sema.NewWeighted(int64(limit)), lockHolder: make(map[string]bool), lock: &sync.Mutex{}, @@ -48,7 +50,7 @@ func (s *PrioritySemaphore) getLimit() int { func (s *PrioritySemaphore) getCurrentPending() []string { var keys []string - for _, item := range s.pending.items { + for _, item := range s.pending.all() { keys = append(keys, item.key) } return keys @@ -85,6 +87,7 @@ func (s *PrioritySemaphore) resize(n int) bool { func (s *PrioritySemaphore) release(key string) bool { s.lock.Lock() defer s.lock.Unlock() + if _, ok := s.lockHolder[key]; ok { delete(s.lockHolder, key) // When semaphore resized downward @@ -94,6 +97,8 @@ func (s *PrioritySemaphore) release(key string) bool { } s.semaphore.Release(1) + s.pending.onRelease(key) + availableLocks := s.limit - len(s.lockHolder) s.log.Infof("Lock has been released by %s. Available locks: %d", key, availableLocks) if s.pending.Len() > 0 { @@ -110,8 +115,9 @@ func (s *PrioritySemaphore) notifyWaiters() { if s.pending.Len() < triggerCount { triggerCount = s.pending.Len() } + all := s.pending.all() for idx := 0; idx < triggerCount; idx++ { - item := s.pending.items[idx] + item := all[idx] wfKey := workflowKey(item) s.log.Debugf("Enqueue the workflow %s", wfKey) s.nextWorkflow(wfKey) @@ -130,7 +136,7 @@ func workflowKey(i *item) string { } // addToQueue adds the holderkey into priority queue that maintains the priority order to acquire the lock. -func (s *PrioritySemaphore) addToQueue(holderKey string, priority int32, creationTime time.Time) { +func (s *PrioritySemaphore) addToQueue(holderKey string, priority int32, creationTime time.Time, syncLockRef *wfv1.Synchronization) { s.lock.Lock() defer s.lock.Unlock() @@ -139,7 +145,7 @@ func (s *PrioritySemaphore) addToQueue(holderKey string, priority int32, creatio return } - s.pending.add(holderKey, priority, creationTime) + s.pending.add(holderKey, priority, creationTime, syncLockRef) s.log.Debugf("Added into queue: %s", holderKey) } diff --git a/workflow/sync/semaphore_test.go b/workflow/sync/semaphore_test.go index 75a0a658a815..da11369db02a 100644 --- a/workflow/sync/semaphore_test.go +++ b/workflow/sync/semaphore_test.go @@ -5,6 +5,8 @@ import ( "time" "github.com/stretchr/testify/assert" + + "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" ) func TestIsSameWorkflowNodeKeys(t *testing.T) { @@ -25,12 +27,13 @@ func TestTryAcquire(t *testing.T) { nextWorkflow := func(key string) { } - s := NewSemaphore("foo", 2, nextWorkflow, "semaphore") + queue := &priorityQueue{itemByKey: make(map[string]*item)} + s := NewSemaphore("foo", 2, nextWorkflow, "semaphore", queue) now := time.Now() - s.addToQueue("default/wf-01", 0, now) - s.addToQueue("default/wf-02", 0, now.Add(time.Second)) - s.addToQueue("default/wf-03", 0, now.Add(2*time.Second)) - s.addToQueue("default/wf-04", 0, now.Add(3*time.Second)) + s.addToQueue("default/wf-01", 0, now, &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-02", 0, now.Add(time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-03", 0, now.Add(2*time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-04", 0, now.Add(3*time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) // verify only the first in line is allowed to acquired the semaphore var acquired bool @@ -58,13 +61,14 @@ func TestNotifyWaitersAcquire(t *testing.T) { notified[key] = true } - s := NewSemaphore("foo", 3, nextWorkflow, "semaphore") + queue := &priorityQueue{itemByKey: make(map[string]*item)} + s := NewSemaphore("foo", 3, nextWorkflow, "semaphore", queue) now := time.Now() - s.addToQueue("default/wf-04", 0, now.Add(3*time.Second)) - s.addToQueue("default/wf-02", 0, now.Add(time.Second)) - s.addToQueue("default/wf-01", 0, now) - s.addToQueue("default/wf-05", 0, now.Add(4*time.Second)) - s.addToQueue("default/wf-03", 0, now.Add(2*time.Second)) + s.addToQueue("default/wf-04", 0, now.Add(3*time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-02", 0, now.Add(time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-01", 0, now, &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-05", 0, now.Add(4*time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-03", 0, now.Add(2*time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) acquired, _ := s.tryAcquire("default/wf-01") assert.True(t, acquired) @@ -93,10 +97,11 @@ func TestNotifyWorkflowFromTemplateSemaphore(t *testing.T) { notified[key] = true } - s := NewSemaphore("foo", 2, nextWorkflow, "semaphore") + queue := &priorityQueue{itemByKey: make(map[string]*item)} + s := NewSemaphore("foo", 2, nextWorkflow, "semaphore", queue) now := time.Now() - s.addToQueue("default/wf-01/nodeid-123", 0, now) - s.addToQueue("default/wf-02/nodeid-456", 0, now.Add(time.Second)) + s.addToQueue("default/wf-01/nodeid-123", 0, now, &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) + s.addToQueue("default/wf-02/nodeid-456", 0, now.Add(time.Second), &v1alpha1.Synchronization{Semaphore: &v1alpha1.SemaphoreRef{}}) acquired, _ := s.tryAcquire("default/wf-01/nodeid-123") assert.True(t, acquired) diff --git a/workflow/sync/sync_manager.go b/workflow/sync/sync_manager.go index 456e10bdf7d0..f96baffcf1e1 100644 --- a/workflow/sync/sync_manager.go +++ b/workflow/sync/sync_manager.go @@ -8,30 +8,34 @@ import ( log "github.com/sirupsen/logrus" runtimeutil "k8s.io/apimachinery/pkg/util/runtime" + "github.com/argoproj/argo-workflows/v3/config" wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" ) type ( - NextWorkflow func(string) - GetSyncLimit func(string) (int, error) - IsWorkflowDeleted func(string) bool + NextWorkflow func(string) + GetSyncLimit func(string) (int, error) + GetSemaphoreQueueType func(string) (config.SemaphoreStrategy, error) + IsWorkflowDeleted func(string) bool ) type Manager struct { - syncLockMap map[string]Semaphore - lock *sync.Mutex - nextWorkflow NextWorkflow - getSyncLimit GetSyncLimit - isWFDeleted IsWorkflowDeleted + syncLockMap map[string]Semaphore + lock *sync.Mutex + nextWorkflow NextWorkflow + getSyncLimit GetSyncLimit + getSemaphoreQueueType GetSemaphoreQueueType + isWFDeleted IsWorkflowDeleted } -func NewLockManager(getSyncLimit GetSyncLimit, nextWorkflow NextWorkflow, isWFDeleted IsWorkflowDeleted) *Manager { +func NewLockManager(getSyncLimit GetSyncLimit, getSemaphoreQueueType GetSemaphoreQueueType, nextWorkflow NextWorkflow, isWFDeleted IsWorkflowDeleted) *Manager { return &Manager{ - syncLockMap: make(map[string]Semaphore), - lock: &sync.Mutex{}, - nextWorkflow: nextWorkflow, - getSyncLimit: getSyncLimit, - isWFDeleted: isWFDeleted, + syncLockMap: make(map[string]Semaphore), + lock: &sync.Mutex{}, + nextWorkflow: nextWorkflow, + getSyncLimit: getSyncLimit, + getSemaphoreQueueType: getSemaphoreQueueType, + isWFDeleted: isWFDeleted, } } @@ -159,10 +163,11 @@ func (cm *Manager) TryAcquire(wf *wfv1.Workflow, nodeName string, syncLockRef *w priority = 0 } creationTime := wf.CreationTimestamp - lock.addToQueue(holderKey, priority, creationTime.Time) + lock.addToQueue(holderKey, priority, creationTime.Time, syncLockRef) ensureInit(wf, syncLockRef.GetType()) currentHolders := cm.getCurrentLockHolders(lockKey) + acquired, msg := lock.tryAcquire(holderKey) if acquired { updated := wf.Status.Synchronization.GetStatus(syncLockRef.GetType()).LockAcquired(holderKey, lockKey, currentHolders) @@ -170,6 +175,7 @@ func (cm *Manager) TryAcquire(wf *wfv1.Workflow, nodeName string, syncLockRef *w } updated := wf.Status.Synchronization.GetStatus(syncLockRef.GetType()).LockWaiting(holderKey, lockKey, currentHolders) + return false, updated, msg, nil } @@ -316,7 +322,23 @@ func (cm *Manager) initializeSemaphore(semaphoreName string) (Semaphore, error) if err != nil { return nil, err } - return NewSemaphore(semaphoreName, limit, cm.nextWorkflow, "semaphore"), nil + semaphoreType, err := cm.getSemaphoreQueueType(semaphoreName) + if err != nil { + return nil, err + } + switch semaphoreType { + case config.SemaphoreStrategyRebalanced: + queue := NewRebalanceQueue() + s := NewSemaphore(semaphoreName, limit, cm.nextWorkflow, "semaphore", queue) + queue.setParentSemaphore(s) // queue needs reference so we must create sem first + log.Infof("Semaphore '%s' has been initialized and is using 'rebalanced' strategy.", semaphoreName) + return s, nil + default: + queue := &priorityQueue{itemByKey: make(map[string]*item)} + s := NewSemaphore(semaphoreName, limit, cm.nextWorkflow, "semaphore", queue) + log.Infof("Semaphore '%s' has been initialized and is using 'default' strategy.", semaphoreName) + return s, nil + } } func (cm *Manager) initializeMutex(mutexName string) Semaphore { diff --git a/workflow/sync/sync_manager_test.go b/workflow/sync/sync_manager_test.go index a7d10b9158e3..cfe6e860db21 100644 --- a/workflow/sync/sync_manager_test.go +++ b/workflow/sync/sync_manager_test.go @@ -14,6 +14,7 @@ import ( "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" + "github.com/argoproj/argo-workflows/v3/config" argoErr "github.com/argoproj/argo-workflows/v3/errors" wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" fakewfclientset "github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned/fake" @@ -27,6 +28,8 @@ metadata: data: workflow: "1" template: "1" + rebalancedsem: "2" + rebalancedsem-strategy: "rebalanced" ` const wfWithStatus = ` @@ -287,6 +290,238 @@ status: startedAt: "2020-06-04T19:55:11Z" ` +const wfWithTmplSemaphoreRebalanced = ` +# Please edit the object below. Lines beginning with a '#' will be ignored, +# and an empty file will abort the edit. If an error occurs while saving this file will be +# reopened with the relevant failures. +# +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + annotations: + workflows.argoproj.io/pod-name-format: v1 + creationTimestamp: "2022-11-03T20:57:30Z" + generateName: semaphore-rebalanced- + generation: 6 + labels: + workflows.argoproj.io/phase: Running + name: semaphore-rebalanced-47qx6 + namespace: default + resourceVersion: "78330" + uid: 37924354-4c9b-45e4-90c7-15036cab5339 +spec: + activeDeadlineSeconds: 100000 + arguments: + parameters: + - name: num + value: "3" + entrypoint: synchronization-tmpl-level-example + podGC: + strategy: OnPodSuccess + podSpecPatch: | + terminationGracePeriodSeconds: 3 + templates: + - inputs: {} + metadata: {} + name: synchronization-tmpl-level-example + outputs: {} + steps: + - - arguments: {} + name: generate + template: gen-number-list + - - arguments: + parameters: + - name: seconds + value: '{{item}}' + name: synchronization-acquire-lock + template: acquire-lock + withParam: '{{steps.generate.outputs.result}}' + - inputs: {} + metadata: {} + name: gen-number-list + outputs: {} + script: + command: + - python + image: python:alpine3.6 + name: "" + resources: {} + source: | + import json + import sys + json.dump([i for i in range(0, {{workflow.parameters.num}})], sys.stdout) + - container: + args: + - sleep 45; echo acquired lock + command: + - sh + - -c + image: alpine:latest + name: "" + resources: {} + inputs: {} + metadata: {} + name: acquire-lock + outputs: {} + synchronization: + semaphore: + configMapKeyRef: + key: rebalancedsem + name: my-config + rebalanceKey: rebalance-key-a + ttlStrategy: + secondsAfterCompletion: 600 +status: + artifactRepositoryRef: + artifactRepository: + archiveLogs: true + s3: + accessKeySecret: + key: accesskey + name: my-minio-cred + bucket: my-bucket + endpoint: minio:9000 + insecure: true + secretKeySecret: + key: secretkey + name: my-minio-cred + configMap: artifact-repositories + key: default-v1 + namespace: argo + conditions: + - status: "False" + type: PodRunning + finishedAt: null + nodes: + semaphore-rebalanced-47qx6: + children: + - semaphore-rebalanced-47qx6-2522652688 + displayName: semaphore-rebalanced-47qx6 + finishedAt: null + id: semaphore-rebalanced-47qx6 + name: semaphore-rebalanced-47qx6 + phase: Running + progress: 1/4 + startedAt: "2022-11-03T20:57:30Z" + templateName: synchronization-tmpl-level-example + templateScope: local/semaphore-rebalanced-47qx6 + type: Steps + semaphore-rebalanced-47qx6-1515848453: + boundaryID: semaphore-rebalanced-47qx6 + children: + - semaphore-rebalanced-47qx6-2332864919 + - semaphore-rebalanced-47qx6-2782851707 + - semaphore-rebalanced-47qx6-2426190623 + displayName: '[1]' + finishedAt: null + id: semaphore-rebalanced-47qx6-1515848453 + name: semaphore-rebalanced-47qx6[1] + phase: Running + progress: 0/3 + startedAt: "2022-11-03T20:57:36Z" + templateScope: local/semaphore-rebalanced-47qx6 + type: StepGroup + semaphore-rebalanced-47qx6-2332864919: + boundaryID: semaphore-rebalanced-47qx6 + displayName: synchronization-acquire-lock(0:0) + finishedAt: null + id: semaphore-rebalanced-47qx6-2332864919 + message: 'Waiting for argo/ConfigMap/workflow-controller-configmap/rebalancedsem + lock. Lock status: 0/0 ' + name: semaphore-rebalanced-47qx6[1].synchronization-acquire-lock(0:0) + phase: Pending + progress: 0/1 + startedAt: "2022-11-03T20:57:36Z" + synchronizationStatus: + waiting: argo/ConfigMap/workflow-controller-configmap/rebalancedsem + templateName: acquire-lock + templateScope: local/semaphore-rebalanced-47qx6 + type: Pod + semaphore-rebalanced-47qx6-2426190623: + boundaryID: semaphore-rebalanced-47qx6 + displayName: synchronization-acquire-lock(2:2) + finishedAt: null + id: semaphore-rebalanced-47qx6-2426190623 + message: 'Waiting for argo/ConfigMap/workflow-controller-configmap/rebalancedsem + lock. Lock status: 0/0 ' + name: semaphore-rebalanced-47qx6[1].synchronization-acquire-lock(2:2) + phase: Pending + progress: 0/1 + startedAt: "2022-11-03T20:57:36Z" + synchronizationStatus: + waiting: argo/ConfigMap/workflow-controller-configmap/rebalancedsem + templateName: acquire-lock + templateScope: local/semaphore-rebalanced-47qx6 + type: Pod + semaphore-rebalanced-47qx6-2522652688: + boundaryID: semaphore-rebalanced-47qx6 + children: + - semaphore-rebalanced-47qx6-2749555789 + displayName: '[0]' + finishedAt: "2022-11-03T20:57:36Z" + id: semaphore-rebalanced-47qx6-2522652688 + name: semaphore-rebalanced-47qx6[0] + phase: Succeeded + progress: 1/4 + resourcesDuration: + cpu: 1 + memory: 0 + startedAt: "2022-11-03T20:57:30Z" + templateScope: local/semaphore-rebalanced-47qx6 + type: StepGroup + semaphore-rebalanced-47qx6-2749555789: + boundaryID: semaphore-rebalanced-47qx6 + children: + - semaphore-rebalanced-47qx6-1515848453 + displayName: generate + finishedAt: "2022-11-03T20:57:32Z" + hostNodeName: k3d-k3s-default-server-0 + id: semaphore-rebalanced-47qx6-2749555789 + name: semaphore-rebalanced-47qx6[0].generate + outputs: + artifacts: + - name: main-logs + s3: + key: semaphore-rebalanced-47qx6/semaphore-rebalanced-47qx6-2749555789/main.log + exitCode: "0" + result: '[0, 1, 2]' + phase: Succeeded + progress: 1/1 + resourcesDuration: + cpu: 1 + memory: 0 + startedAt: "2022-11-03T20:57:30Z" + templateName: gen-number-list + templateScope: local/semaphore-rebalanced-47qx6 + type: Pod + semaphore-rebalanced-47qx6-2782851707: + boundaryID: semaphore-rebalanced-47qx6 + displayName: synchronization-acquire-lock(1:1) + finishedAt: null + id: semaphore-rebalanced-47qx6-2782851707 + message: 'Waiting for argo/ConfigMap/workflow-controller-configmap/rebalancedsem + lock. Lock status: 0/0 ' + name: semaphore-rebalanced-47qx6[1].synchronization-acquire-lock(1:1) + phase: Pending + progress: 0/1 + startedAt: "2022-11-03T20:57:36Z" + synchronizationStatus: + waiting: argo/ConfigMap/workflow-controller-configmap/rebalancedsem + templateName: acquire-lock + templateScope: local/semaphore-rebalanced-47qx6 + type: Pod + phase: Running + progress: 1/4 + resourcesDuration: + cpu: 1 + memory: 0 + startedAt: "2022-11-03T20:57:30Z" + synchronization: + semaphore: + waiting: + - semaphore: argo/ConfigMap/workflow-controller-configmap/rebalancedsem +` + const wfWithMutex = ` apiVersion: argoproj.io/v1alpha1 kind: Workflow @@ -306,6 +541,10 @@ spec: args: ["hello world"] ` +var GetSemaphoreQueTypeAlwaysDefault = func(s string) (config.SemaphoreStrategy, error) { + return config.SemaphoreStrategyDefault, nil +} + var WorkflowExistenceFunc = func(s string) bool { return false } @@ -333,6 +572,36 @@ func GetSyncLimitFunc(kube *fake.Clientset) func(string) (int, error) { return syncLimitConfig } +func GetSemaphoreQueue(kube *fake.Clientset) func(string) (config.SemaphoreStrategy, error) { + syncLimitConfig := func(lockName string) (config.SemaphoreStrategy, error) { + items := strings.Split(lockName, "/") + if len(items) < 4 { + return config.SemaphoreStrategyDefault, argoErr.New(argoErr.CodeBadRequest, "Invalid Config Map Key") + } + + ctx := context.Background() + configMap, err := kube.CoreV1().ConfigMaps(items[0]).Get(ctx, items[2], metav1.GetOptions{}) + if err != nil { + return config.SemaphoreStrategyDefault, err + } + + value, found := configMap.Data[items[3]+"-strategy"] + + if !found { + return config.SemaphoreStrategyDefault, nil + } + + if value == string(config.SemaphoreStrategyDefault) { + return config.SemaphoreStrategyDefault, nil + } else if value == string(config.SemaphoreStrategyRebalanced) { + return config.SemaphoreStrategyRebalanced, nil + } else { + return config.SemaphoreStrategyDefault, fmt.Errorf("unknown semaphore strategy '%s' for lock '%s'", value, lockName) + } + } + return syncLimitConfig +} + func TestSemaphoreWfLevel(t *testing.T) { kube := fake.NewSimpleClientset() var cm v1.ConfigMap @@ -344,7 +613,7 @@ func TestSemaphoreWfLevel(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("InitializeSynchronization", func(t *testing.T) { - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithStatus) wfclientset := fakewfclientset.NewSimpleClientset(wf) @@ -355,7 +624,7 @@ func TestSemaphoreWfLevel(t *testing.T) { assert.Equal(t, 1, len(concurrenyMgr.syncLockMap)) }) t.Run("InitializeSynchronizationWithInvalid", func(t *testing.T) { - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithStatus) invalidSync := []wfv1.SemaphoreHolding{{Semaphore: "default/configmap/my-config1/workflow", Holders: []string{"hello-world-vcrg5"}}} @@ -369,7 +638,7 @@ func TestSemaphoreWfLevel(t *testing.T) { t.Run("WfLevelAcquireAndRelease", func(t *testing.T) { var nextKey string - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { nextKey = key }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithSemaphore) @@ -443,11 +712,11 @@ func TestSemaphoreWfLevel(t *testing.T) { sema := concurrenyMgr.syncLockMap["default/ConfigMap/my-config/workflow"].(*PrioritySemaphore) assert.NotNil(t, sema) - assert.Len(t, sema.pending.items, 2) + assert.Len(t, sema.pending.all(), 2) concurrenyMgr.ReleaseAll(wf1) - assert.Len(t, sema.pending.items, 1) + assert.Len(t, sema.pending.all(), 1) concurrenyMgr.ReleaseAll(wf3) - assert.Len(t, sema.pending.items, 0) + assert.Len(t, sema.pending.all(), 0) }) } @@ -462,7 +731,7 @@ func TestResizeSemaphoreSize(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("WfLevelAcquireAndRelease", func(t *testing.T) { - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithSemaphore) wf.CreationTimestamp = metav1.Time{Time: time.Now()} @@ -528,9 +797,10 @@ func TestSemaphoreTmplLevel(t *testing.T) { assert.NoError(t, err) syncLimitFunc := GetSyncLimitFunc(kube) + getSemaphoreQueueType := GetSemaphoreQueue(kube) t.Run("TemplateLevelAcquireAndRelease", func(t *testing.T) { // var nextKey string - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { // nextKey = key }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithTmplSemaphore) @@ -572,6 +842,85 @@ func TestSemaphoreTmplLevel(t *testing.T) { assert.NotNil(t, wf.Status.Synchronization.Semaphore) assert.Equal(t, "semaphore-tmpl-level-xjvln-1607747183", wf.Status.Synchronization.Semaphore.Holding[0].Holders[0]) }) + + t.Run("TemplateLevelRebalanced", func(t *testing.T) { + concurrenyMgr := NewLockManager(syncLimitFunc, getSemaphoreQueueType, func(key string) { + }, WorkflowExistenceFunc) + wfRebalanceKeyA := wfv1.MustUnmarshalWorkflow(wfWithTmplSemaphoreRebalanced) + wfRebalanceKeyASync := wfRebalanceKeyA.Spec.Templates[2] + + iterTmpl := strings.ReplaceAll(wfWithTmplSemaphoreRebalanced, "semaphore-rebalanced-47qx6", "semaphore-rebalanced-90ab3") + iterTmpl = strings.ReplaceAll(iterTmpl, "rebalance-key-a", "rebalance-key-b") + wfRebalanceKeyB := wfv1.MustUnmarshalWorkflow(iterTmpl) + wfRebalanceKeyBSync := wfRebalanceKeyB.Spec.Templates[2] + + // semaphore-rebalanced-47qx6-2332864919 (wfRebalanceKeyA) tries to acquire a lock and succeeds + status, wfUpdate, msg, err := concurrenyMgr.TryAcquire(wfRebalanceKeyA, "semaphore-rebalanced-47qx6-2332864919", wfRebalanceKeyASync.Synchronization) + assert.NoError(t, err) + assert.Empty(t, msg) + assert.True(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization.Semaphore) + assert.Equal(t, "semaphore-rebalanced-47qx6-2332864919", wfRebalanceKeyA.Status.Synchronization.Semaphore.Holding[0].Holders[0]) + + // semaphore-rebalanced-47qx6-2782851707 (wfRebalanceKeyA) tries to acquire a lock and succeeds + status, wfUpdate, msg, err = concurrenyMgr.TryAcquire(wfRebalanceKeyA, "semaphore-rebalanced-47qx6-2782851707", wfRebalanceKeyASync.Synchronization) + assert.NoError(t, err) + assert.Empty(t, msg) + assert.True(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization.Semaphore) + assert.Equal(t, "semaphore-rebalanced-47qx6-2782851707", wfRebalanceKeyA.Status.Synchronization.Semaphore.Holding[0].Holders[1]) + + // semaphore-rebalanced-47qx6-2426190623 (wfRebalanceKeyA) tries to acquire a lock and fails because we've reached limit + status, wfUpdate, msg, err = concurrenyMgr.TryAcquire(wfRebalanceKeyA, "semaphore-rebalanced-47qx6-2426190623", wfRebalanceKeyASync.Synchronization) + assert.NoError(t, err) + assert.Contains(t, msg, "Waiting for default/ConfigMap/my-config/rebalancedsem lock. Lock status: 0/2") + assert.False(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization.Semaphore) + + // currently 2 lock holders, both from wfRebalanceKeyA + assert.Equal(t, len(wfRebalanceKeyA.Status.Synchronization.Semaphore.Holding[0].Holders), 2) + + // semaphore-rebalanced-90ab3-2332864919 (wfRebalanceKeyB) tries to acquire a lock and fails because we've reached limit + status, wfUpdate, msg, err = concurrenyMgr.TryAcquire(wfRebalanceKeyB, "semaphore-rebalanced-90ab3-2332864919", wfRebalanceKeyBSync.Synchronization) + assert.NoError(t, err) + assert.Contains(t, msg, "Waiting for default/ConfigMap/my-config/rebalancedsem lock. Lock status: 0/2") + assert.False(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyB.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyB.Status.Synchronization.Semaphore) + + // one node from wfRebalanceKeyA finishes + concurrenyMgr.Release(wfRebalanceKeyA, "semaphore-rebalanced-47qx6-2332864919", wfRebalanceKeyASync.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization.Semaphore) + assert.Equal(t, len(wfRebalanceKeyA.Status.Synchronization.Semaphore.Holding[0].Holders), 1) + + // semaphore-rebalanced-47qx6-2426190623 (wfRebalanceKeyA) tries to acquire a lock and STILL fails because there are two distinct rebalance keys + // in the list of waiting resources + status, wfUpdate, msg, err = concurrenyMgr.TryAcquire(wfRebalanceKeyA, "semaphore-rebalanced-47qx6-2426190623", wfRebalanceKeyASync.Synchronization) + assert.NoError(t, err) + assert.NotEmpty(t, msg) + // assert.Contains(t, msg, "Waiting for default/ConfigMap/my-config/rebalancedsem lock. Lock status: 0/2 ") + assert.False(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyA.Status.Synchronization.Semaphore) + + // wfRebalanceKeyB tries to acquire 1 and succeeds because wfRebalanceKeyB currently has not acquired any keys + status, wfUpdate, msg, err = concurrenyMgr.TryAcquire(wfRebalanceKeyB, "semaphore-rebalanced-90ab3-2332864919", wfRebalanceKeyBSync.Synchronization) + assert.NoError(t, err) + assert.Empty(t, msg) + assert.True(t, status) + assert.True(t, wfUpdate) + assert.NotNil(t, wfRebalanceKeyB.Status.Synchronization) + assert.NotNil(t, wfRebalanceKeyB.Status.Synchronization.Semaphore) + }) } func TestTriggerWFWithAvailableLock(t *testing.T) { @@ -588,7 +937,7 @@ func TestTriggerWFWithAvailableLock(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("TriggerWfsWithAvailableLocks", func(t *testing.T) { triggerCount := 0 - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { triggerCount++ }, WorkflowExistenceFunc) var wfs []wfv1.Workflow @@ -624,7 +973,7 @@ func TestMutexWfLevel(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("WorkflowLevelMutexAcquireAndRelease", func(t *testing.T) { // var nextKey string - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { // nextKey = key }, WorkflowExistenceFunc) wf := wfv1.MustUnmarshalWorkflow(wfWithMutex) @@ -656,11 +1005,11 @@ func TestMutexWfLevel(t *testing.T) { mutex := concurrenyMgr.syncLockMap["default/Mutex/my-mutex"].(*PriorityMutex) assert.NotNil(t, mutex) - assert.Len(t, mutex.mutex.pending.items, 2) + assert.Len(t, mutex.mutex.pending.all(), 2) concurrenyMgr.ReleaseAll(wf1) - assert.Len(t, mutex.mutex.pending.items, 1) + assert.Len(t, mutex.mutex.pending.all(), 1) concurrenyMgr.ReleaseAll(wf2) - assert.Len(t, mutex.mutex.pending.items, 0) + assert.Len(t, mutex.mutex.pending.all(), 0) }) } @@ -677,7 +1026,7 @@ func TestCheckWorkflowExistence(t *testing.T) { syncLimitFunc := GetSyncLimitFunc(kube) t.Run("WorkflowDeleted", func(t *testing.T) { - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { // nextKey = key }, func(s string) bool { return strings.Contains(s, "test1") @@ -846,7 +1195,7 @@ status: `) syncLimitFunc := GetSyncLimitFunc(kube) - concurrenyMgr := NewLockManager(syncLimitFunc, func(key string) { + concurrenyMgr := NewLockManager(syncLimitFunc, GetSemaphoreQueTypeAlwaysDefault, func(key string) { // nextKey = key }, WorkflowExistenceFunc) t.Run("InitializeMutex", func(t *testing.T) { diff --git a/workflow/sync/throttler.go b/workflow/sync/throttler.go index 674cff254908..5660b1bb5329 100644 --- a/workflow/sync/throttler.go +++ b/workflow/sync/throttler.go @@ -95,7 +95,7 @@ func (t *throttler) Add(key Key, priority int32, creationTime time.Time) { if _, ok := t.pending[bucketKey]; !ok { t.pending[bucketKey] = &priorityQueue{itemByKey: make(map[string]*item)} } - t.pending[bucketKey].add(key, priority, creationTime) + t.pending[bucketKey].add(key, priority, creationTime, nil) t.queueThrottled(bucketKey) } @@ -151,6 +151,10 @@ type priorityQueue struct { itemByKey map[string]*item } +// this is a no-op but helps us implement SemaphoreStrategyQueue +func (pq *priorityQueue) onRelease(key Key) { +} + func (pq *priorityQueue) pop() *item { return heap.Pop(pq).(*item) } @@ -159,7 +163,7 @@ func (pq *priorityQueue) peek() *item { return pq.items[0] } -func (pq *priorityQueue) add(key Key, priority int32, creationTime time.Time) { +func (pq *priorityQueue) add(key Key, priority int32, creationTime time.Time, _ *wfv1.Synchronization) { if res, ok := pq.itemByKey[key]; ok { if res.priority != priority { res.priority = priority @@ -170,6 +174,10 @@ func (pq *priorityQueue) add(key Key, priority int32, creationTime time.Time) { } } +func (pq *priorityQueue) all() []*item { + return pq.items +} + func (pq *priorityQueue) remove(key Key) { if item, ok := pq.itemByKey[key]; ok { heap.Remove(pq, item.index)