diff --git a/docs/components/SiteRuntime.md b/docs/components/SiteRuntime.md index 1203acbe..fd9dcdfa 100644 --- a/docs/components/SiteRuntime.md +++ b/docs/components/SiteRuntime.md @@ -205,7 +205,7 @@ Both `AlarmActor` and `NativeAlarmActor` tell the `InstanceActor` an `AlarmState | `static_attribute_overrides` | Runtime attribute writes (`SetAttribute` on static attrs) | Yes — cleared by `ClearStaticOverridesAsync` | | `native_alarm_state` | Mirrored native alarm conditions (survives failover) | Yes — cleared by `ClearNativeAlarmsForInstanceAsync` | | `shared_scripts` | Shared script code from artifact deployments | No | -| `external_systems` | External system definitions | No | +| `external_systems` | External system definitions (incl. `timeout_seconds`, and `max_retries`/`retry_delay_ms` — the deployed store-and-forward retry policy, `0` = use the engine default) | No | | `database_connections` | Database connection strings | No | | `data_connection_definitions` | OPC UA / MxGateway endpoint definitions | No | | `notification_lists` | Notification list definitions | No | diff --git a/docs/components/StoreAndForward.md b/docs/components/StoreAndForward.md index a770579f..29e4ea69 100644 --- a/docs/components/StoreAndForward.md +++ b/docs/components/StoreAndForward.md @@ -51,6 +51,8 @@ The retry interval is fixed — not exponential. There is no maximum buffer size `StoreAndForwardMessage.MaxRetries` controls how many background-sweep attempts the engine makes before parking. `MaxRetries = 0` means **no limit** — the message retries on every sweep until delivered and is never parked for retry exhaustion. It is not a "never retry" value; callers that want unbounded retry pass `maxRetries: 0` explicitly. The `EnqueueAsync` `maxRetries` parameter defaults to `StoreAndForwardOptions.DefaultMaxRetries` (50). +**The source-entity `0` means the opposite, and the gateways convert.** On an `ExternalSystemDefinition` / `DatabaseConnectionDefinition`, `MaxRetries = 0` (and `RetryDelay = TimeSpan.Zero`) mean *unset*, not *unbounded* — so `ExternalSystemClient.CachedCallAsync` and `DatabaseGateway` pass `system.MaxRetries > 0 ? system.MaxRetries : null`, letting the bounded engine default apply. Forwarding the entity's `0` verbatim would make every unconfigured cached call retry forever. The external system's values only actually reach a site as of deferred-work row 27; before that the artifact did not carry them. + ### Messages not cleared on instance deletion When an instance is deleted, its buffered S&F messages are not removed. `StoreAndForwardMessage.OriginInstanceName` records the originating instance at enqueue time so the buffer can continue to deliver and so the central UI can attribute parked messages even after the instance is gone. diff --git a/docs/deployment/topology-guide.md b/docs/deployment/topology-guide.md index cc279f92..5320168c 100644 --- a/docs/deployment/topology-guide.md +++ b/docs/deployment/topology-guide.md @@ -291,6 +291,18 @@ will run, but they will not converge, and the divergence is silent. Stop both nodes of a site pair, upgrade both, then start both. +**A release that adds a column to a replicated table is the same constraint, enforced louder.** +`ReplicatedTable.ComputeDigest` hashes every column name and declared type, and the sync handshake +compares those digests fail-closed — so a mixed-version pair whose builds disagree about a table's +columns does not diverge silently, it refuses to sync with a `LocalDbSchemaMismatchException`. +Stopping and starting both nodes together, which is already the rule above, is the whole fix; no +manual trigger or oplog migration is needed, because `RegisterReplicated` re-reads +`PRAGMA table_info` on every boot and rebuilds the capture triggers (DROP + CREATE) over the +current column set. The site schema's own `AddColumnIfMissing` runs before registration on that +same boot, so a node picks up the new columns and the matching triggers in one start. +(Most recent instance: `external_systems` gained `max_retries` / `retry_delay_ms` for the +per-system store-and-forward retry policy.) + **Related bound — do not leave one node of a pair offline for long.** A node absent for longer than `LocalDb:Replication:TombstoneRetention` (default **7 days**) can **resurrect deleted rows** when it rejoins: deletes replicate as HLC-ordered tombstones, and once a tombstone is pruned there is diff --git a/docs/requirements/Component-CLI.md b/docs/requirements/Component-CLI.md index 068cfb16..b7f89a89 100644 --- a/docs/requirements/Component-CLI.md +++ b/docs/requirements/Component-CLI.md @@ -194,8 +194,8 @@ scadabridge data-connection certs remove --site --thumbprint ``` scadabridge external-system list scadabridge external-system get --id -scadabridge external-system create --name --endpoint-url --auth-type [--auth-config ] -scadabridge external-system update --id [--name ] [--endpoint-url ] [--auth-type ] [--auth-config ] +scadabridge external-system create --name --endpoint-url --auth-type [--auth-config ] [--timeout-seconds ] [--max-retries ] [--retry-delay-seconds ] +scadabridge external-system update --id [--name ] [--endpoint-url ] [--auth-type ] [--auth-config ] [--timeout-seconds ] [--max-retries ] [--retry-delay-seconds ] scadabridge external-system delete --id scadabridge external-system method list --external-system-id scadabridge external-system method get --id diff --git a/docs/requirements/Component-ExternalSystemGateway.md b/docs/requirements/Component-ExternalSystemGateway.md index b578f67d..2e100873 100644 --- a/docs/requirements/Component-ExternalSystemGateway.md +++ b/docs/requirements/Component-ExternalSystemGateway.md @@ -42,7 +42,7 @@ Each external system definition includes: **Legacy colon form (deprecated):** a value that does not start with `{` is parsed with the historical colon-split rules for backward compatibility — API Key as `HeaderName:KeyValue` (or a bare `KeyValue` using the default `X-API-Key` header), Basic Auth as `username:password`. This form cannot represent keys or passwords that contain `:` and is retained only so existing rows keep working; new definitions should use the JSON form. Malformed JSON (a value that starts with `{` but does not parse, or yields no usable `key`/`username`) is **not** an exception — the request is sent without the auth header and a warning is logged (the configuration value itself is never logged). - **Timeout**: Per-system timeout for all method calls (e.g., 30 seconds). Applies to the HTTP request round-trip. `0` (the default) means "unset" — the gateway's configured `DefaultHttpTimeout` applies instead. Set via the Central UI External System form's "Timeout (seconds)" field; ships to sites in the deployment artifact like the other definition fields. -- **Retry Settings**: Max retry count, fixed time between retries (used by Store-and-Forward Engine for transient failures only). +- **Retry Settings**: Max retry count, fixed time between retries (used by Store-and-Forward Engine for transient failures only). Both are **`0` = unset**, in which case the engine's `DefaultMaxRetries` (50) and `DefaultRetryInterval` (30 s) apply — note this is the inverse of the S&F engine's own `MaxRetries` contract, where a stored `0` means *unbounded* retry; the gateway translates an unset `0` to "no per-system override" rather than passing it through. Authored via the Central UI External System form ("Max Retries" / "Retry Delay (seconds)") or `external-system create|update --max-retries --retry-delay-seconds`, and **deployed to sites in the external-system artifact** alongside the timeout, so the site's cached-call buffering honours the configured policy. (Before the row-27 fix the artifact carried no retry fields and the site table had no columns for them, so a centrally-configured policy was silently ignored and every cached call used the engine default.) - **Method Definitions**: List of available API methods, each with: - Method name. - **HTTP method**: GET, POST, PUT, PATCH, or DELETE. diff --git a/docs/requirements/Component-StoreAndForward.md b/docs/requirements/Component-StoreAndForward.md index 669c583c..589939ec 100644 --- a/docs/requirements/Component-StoreAndForward.md +++ b/docs/requirements/Component-StoreAndForward.md @@ -63,6 +63,19 @@ For the external-system-call and cached-database-write categories, retry setting - **External systems**: Each external system definition includes max retry count and time between retries. - **Cached database writes**: Each database connection definition includes max retry count and time between retries. +Both are carried to the site in the deployment artifact and read back out of the site's own +tables by the gateway, which passes them to `EnqueueAsync`. An **unset** source-entity value +(`MaxRetries` `0` / `RetryDelay` `TimeSpan.Zero`) is passed as `null`, so the engine's +`DefaultMaxRetries` (50) and `DefaultRetryInterval` (30 s) apply — roughly 25 minutes to park. +The translation is deliberate and must not be removed: the engine reads a stored `MaxRetries` +of `0` as **no limit**, so forwarding an unconfigured entity's `0` verbatim would turn every +cached call into an unbounded retry loop. + +> Until deferred-work row 27 was fixed, this was true of database connections only. +> `ExternalSystemArtifact` carried no retry fields and the site `external_systems` table had no +> columns for them, so an external system's centrally-configured policy never reached the site +> and every external-system cached call silently used the 50 x 30 s default. + The **notification** category retries differently: it has no source-entity setting. The site→central forward uses a single fixed retry interval configured in the host `appsettings.json`. This interval is infrastructure config for reaching the central cluster, not a per-notification-list setting. It applies uniformly to every buffered notification regardless of its target list. A buffered notification is retried at that interval until central acks it; the engine's `DefaultMaxRetries` cap still applies (matching the cached-call categories) and a notification whose retries are exhausted under a sustained central outage parks like any other buffered message. The cap is sized so the normal central-recovery window stays well inside it — central, once reachable, owns delivery, retry, and parking from the ack point on. The retry interval is **fixed** (not exponential backoff). Fixed interval is sufficient for the expected use cases. diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs index 3df4dc10..d3c908f8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs @@ -50,6 +50,9 @@ public static class ExternalSystemCommands var authTypeOption = new Option("--auth-type") { Description = "Auth type", Required = true }; var authConfigOption = new Option("--auth-config") { Description = "Auth configuration JSON" }; var timeoutOption = new Option("--timeout-seconds") { Description = "Per-system HTTP timeout in seconds (0 = use gateway default); omit to preserve" }; + var maxRetriesOption = new Option("--max-retries") { Description = "Store-and-forward retry budget for cached calls (0 = use engine default); omit to preserve" }; + var retryDelayOption = new Option("--retry-delay-seconds") { Description = "Fixed interval between store-and-forward retries, in seconds (0 = use engine default); omit to preserve" }; + retryDelayOption.Aliases.Add("--retry-delay"); var cmd = new Command("update") { Description = "Update an external system" }; cmd.Add(idOption); @@ -58,6 +61,8 @@ public static class ExternalSystemCommands cmd.Add(authTypeOption); cmd.Add(authConfigOption); cmd.Add(timeoutOption); + cmd.Add(maxRetriesOption); + cmd.Add(retryDelayOption); cmd.SetAction(async (ParseResult result) => { var id = result.GetValue(idOption); @@ -66,9 +71,13 @@ public static class ExternalSystemCommands var authType = result.GetValue(authTypeOption)!; var authConfig = result.GetValue(authConfigOption); var timeoutSeconds = result.GetValue(timeoutOption); + var maxRetries = result.GetValue(maxRetriesOption); + var retryDelaySeconds = result.GetValue(retryDelayOption); return await CommandHelpers.ExecuteCommandAsync( result, urlOption, formatOption, usernameOption, passwordOption, - new UpdateExternalSystemCommand(id, name, endpointUrl, authType, authConfig, timeoutSeconds)); + new UpdateExternalSystemCommand(id, name, endpointUrl, authType, authConfig, timeoutSeconds, + maxRetries, + retryDelaySeconds is { } rd ? TimeSpan.FromSeconds(rd) : null)); }); return cmd; } @@ -91,6 +100,9 @@ public static class ExternalSystemCommands var authTypeOption = new Option("--auth-type") { Description = "Auth type (ApiKey, BasicAuth)", Required = true }; var authConfigOption = new Option("--auth-config") { Description = "Auth configuration JSON" }; var timeoutOption = new Option("--timeout-seconds") { Description = "Per-system HTTP timeout in seconds (0 = use gateway default)" }; + var maxRetriesOption = new Option("--max-retries") { Description = "Store-and-forward retry budget for cached calls (0 = use engine default)" }; + var retryDelayOption = new Option("--retry-delay-seconds") { Description = "Fixed interval between store-and-forward retries, in seconds (0 = use engine default)" }; + retryDelayOption.Aliases.Add("--retry-delay"); var cmd = new Command("create") { Description = "Create an external system" }; cmd.Add(nameOption); @@ -98,6 +110,8 @@ public static class ExternalSystemCommands cmd.Add(authTypeOption); cmd.Add(authConfigOption); cmd.Add(timeoutOption); + cmd.Add(maxRetriesOption); + cmd.Add(retryDelayOption); cmd.SetAction(async (ParseResult result) => { var name = result.GetValue(nameOption)!; @@ -105,9 +119,13 @@ public static class ExternalSystemCommands var authType = result.GetValue(authTypeOption)!; var authConfig = result.GetValue(authConfigOption); var timeoutSeconds = result.GetValue(timeoutOption); + var maxRetries = result.GetValue(maxRetriesOption); + var retryDelaySeconds = result.GetValue(retryDelayOption); return await CommandHelpers.ExecuteCommandAsync( result, urlOption, formatOption, usernameOption, passwordOption, - new CreateExternalSystemCommand(name, endpointUrl, authType, authConfig, timeoutSeconds)); + new CreateExternalSystemCommand(name, endpointUrl, authType, authConfig, timeoutSeconds, + maxRetries, + retryDelaySeconds is { } rd ? TimeSpan.FromSeconds(rd) : null)); }); return cmd; } diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/README.md b/src/ZB.MOM.WW.ScadaBridge.CLI/README.md index dce85eee..5e9a4e38 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/README.md +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/README.md @@ -1206,7 +1206,7 @@ scadabridge --url external-system list Register an external HTTP system that scripts can call. ```sh -scadabridge --url external-system create --name --endpoint-url --auth-type [--auth-config ] +scadabridge --url external-system create --name --endpoint-url --auth-type [--auth-config ] [--timeout-seconds ] [--max-retries ] [--retry-delay-seconds ] ``` | Option | Required | Description | @@ -1215,6 +1215,13 @@ scadabridge --url external-system create --name --endpoint-url external-system update --id --name --endpoint-url --auth-type [--auth-config ] +scadabridge --url external-system update --id --name --endpoint-url --auth-type [--auth-config ] [--timeout-seconds ] [--max-retries ] [--retry-delay-seconds ] ``` | Option | Required | Description | @@ -1231,7 +1238,14 @@ scadabridge --url external-system update --id --name --endp | `--name` | yes | Display name | | `--endpoint-url` | yes | Base URL | | `--auth-type` | yes | Authentication type | -| `--auth-config` | no | Updated auth credentials as a JSON string | +| `--auth-config` | no | Updated auth credentials as a JSON string; omit to preserve the stored value | +| `--timeout-seconds` | no | Per-system HTTP round-trip timeout; omit to preserve | +| `--max-retries` | no | Store-and-forward retry budget for this system's `CachedCall`s; omit to preserve | +| `--retry-delay-seconds` | no | Fixed interval between store-and-forward retries; omit to preserve. Alias: `--retry-delay` | + +Note the asymmetry with the required fields above: the four optional settings follow an +**omit-to-preserve** rule, so a rename does not silently reset a system's auth config, +timeout, or retry policy. #### `external-system delete` diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Artifacts/ExternalSystemArtifact.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Artifacts/ExternalSystemArtifact.cs index 6e689145..09ec9fd3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Artifacts/ExternalSystemArtifact.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Artifacts/ExternalSystemArtifact.cs @@ -1,9 +1,41 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts; +/// +/// A single external HTTP system, flattened for deployment to a site. +/// +/// Unique system name — the key scripts call it by. +/// Base URL of the system's HTTP endpoint. +/// Authentication type identifier (e.g. ApiKey, BasicAuth). +/// JSON-serialized authentication configuration for . +/// JSON-serialized method list, or null when the system defines none. +/// +/// Per-system HTTP round-trip timeout in seconds. 0 = unset — the gateway's configured +/// DefaultHttpTimeout applies. +/// +/// +/// Store-and-Forward retry budget for this system's cached calls. 0 = unset — the engine's +/// DefaultMaxRetries applies. +/// +/// 0 means "unset", not "no limit", at THIS layer — the inverse of +/// StoreAndForwardMessage.MaxRetries, where a stored 0 means unbounded retry. The two +/// meanings are reconciled in ExternalSystemClient.CachedCallAsync, which passes a 0 +/// through as null so the bounded engine default applies rather than an unbounded retry +/// loop. Keeping "unset" as 0 here (rather than a nullable) matches +/// , the non-nullable +/// ExternalSystemDefinition.MaxRetries entity property this is projected from, and the +/// proto3 scalar it is carried on. +/// +/// +/// +/// Fixed interval between Store-and-Forward retry sweeps for this system's cached calls. +/// = unset — the engine's DefaultRetryInterval applies. +/// public record ExternalSystemArtifact( string Name, string EndpointUrl, string AuthType, string? AuthConfiguration, string? MethodDefinitionsJson, - int TimeoutSeconds = 0); + int TimeoutSeconds = 0, + int MaxRetries = 0, + TimeSpan RetryDelay = default); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ExternalSystemCommands.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ExternalSystemCommands.cs index 856749b6..8cea22ec 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ExternalSystemCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ExternalSystemCommands.cs @@ -2,8 +2,23 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; public record ListExternalSystemsCommand; public record GetExternalSystemCommand(int ExternalSystemId); -public record CreateExternalSystemCommand(string Name, string EndpointUrl, string AuthType, string? AuthConfiguration, int? TimeoutSeconds = null); -public record UpdateExternalSystemCommand(int ExternalSystemId, string Name, string EndpointUrl, string AuthType, string? AuthConfiguration, int? TimeoutSeconds = null); +/// +/// Creates an external HTTP system. +/// +/// +/// and are the Store-and-Forward +/// retry policy applied to this system's ExternalSystem.CachedCall buffering. Both are +/// nullable on the wire so "omit" is distinguishable from "set to 0"; a null (or an explicit 0) +/// stores the entity's unset value, which the site gateway translates into the engine's +/// DefaultMaxRetries/DefaultRetryInterval. +/// +public record CreateExternalSystemCommand(string Name, string EndpointUrl, string AuthType, string? AuthConfiguration, int? TimeoutSeconds = null, int? MaxRetries = null, TimeSpan? RetryDelay = null); + +/// +/// Updates an external HTTP system. Nullable members follow the "omit to preserve" convention — +/// a null leaves the stored value untouched. +/// +public record UpdateExternalSystemCommand(int ExternalSystemId, string Name, string EndpointUrl, string AuthType, string? AuthConfiguration, int? TimeoutSeconds = null, int? MaxRetries = null, TimeSpan? RetryDelay = null); public record DeleteExternalSystemCommand(int ExternalSystemId); // External System Methods diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs index 97508ba8..357fe918 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs @@ -506,7 +506,9 @@ public static class SiteCommandDtoMapper AuthType = artifact.AuthType, AuthConfiguration = OrEmpty(artifact.AuthConfiguration), MethodDefinitionsJson = OrEmpty(artifact.MethodDefinitionsJson), - TimeoutSeconds = artifact.TimeoutSeconds + TimeoutSeconds = artifact.TimeoutSeconds, + MaxRetries = artifact.MaxRetries, + RetryDelay = Duration.FromTimeSpan(artifact.RetryDelay) }; } @@ -523,7 +525,9 @@ public static class SiteCommandDtoMapper dto.AuthType, NullIfEmpty(dto.AuthConfiguration), NullIfEmpty(dto.MethodDefinitionsJson), - dto.TimeoutSeconds); + dto.TimeoutSeconds, + dto.MaxRetries, + dto.RetryDelay?.ToTimeSpan() ?? TimeSpan.Zero); } /// Projects a onto the wire. diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto index 8c6fa912..813a09ad 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto @@ -224,6 +224,11 @@ message ExternalSystemArtifactDto { string auth_configuration = 4; // empty string represents null string method_definitions_json = 5; // empty string represents null int32 timeout_seconds = 6; + // Store-and-Forward retry policy for this system's cached calls. Additive (fields 7-8); + // a pre-existing site decodes them as 0/absent, which is exactly the "unset" value that + // makes the engine defaults apply — i.e. the old behaviour. + int32 max_retries = 7; + google.protobuf.Duration retry_delay = 8; } message DatabaseConnectionArtifactDto { diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs index fda7176e..fa79f645 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs @@ -64,438 +64,439 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { "Lmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAibwoXU2hhcmVkU2NyaXB0QXJ0", "aWZhY3REdG8SDAoEbmFtZRgBIAEoCRIMCgRjb2RlGAIgASgJEh0KFXBhcmFt", "ZXRlcl9kZWZpbml0aW9ucxgDIAEoCRIZChFyZXR1cm5fZGVmaW5pdGlvbhgE", - "IAEoCSKoAQoZRXh0ZXJuYWxTeXN0ZW1BcnRpZmFjdER0bxIMCgRuYW1lGAEg", + "IAEoCSLtAQoZRXh0ZXJuYWxTeXN0ZW1BcnRpZmFjdER0bxIMCgRuYW1lGAEg", "ASgJEhQKDGVuZHBvaW50X3VybBgCIAEoCRIRCglhdXRoX3R5cGUYAyABKAkS", "GgoSYXV0aF9jb25maWd1cmF0aW9uGAQgASgJEh8KF21ldGhvZF9kZWZpbml0", - "aW9uc19qc29uGAUgASgJEhcKD3RpbWVvdXRfc2Vjb25kcxgGIAEoBSKNAQod", - "RGF0YWJhc2VDb25uZWN0aW9uQXJ0aWZhY3REdG8SDAoEbmFtZRgBIAEoCRIZ", - "ChFjb25uZWN0aW9uX3N0cmluZxgCIAEoCRITCgttYXhfcmV0cmllcxgDIAEo", - "BRIuCgtyZXRyeV9kZWxheRgEIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJh", - "dGlvbiJFChtOb3RpZmljYXRpb25MaXN0QXJ0aWZhY3REdG8SDAoEbmFtZRgB", - "IAEoCRIYChByZWNpcGllbnRfZW1haWxzGAIgAygJIqABChlEYXRhQ29ubmVj", - "dGlvbkFydGlmYWN0RHRvEgwKBG5hbWUYASABKAkSEAoIcHJvdG9jb2wYAiAB", - "KAkSIgoacHJpbWFyeV9jb25maWd1cmF0aW9uX2pzb24YAyABKAkSIQoZYmFj", - "a3VwX2NvbmZpZ3VyYXRpb25fanNvbhgEIAEoCRIcChRmYWlsb3Zlcl9yZXRy", - "eV9jb3VudBgFIAEoBSKtAQocU210cENvbmZpZ3VyYXRpb25BcnRpZmFjdER0", - "bxIMCgRuYW1lGAEgASgJEg4KBnNlcnZlchgCIAEoCRIMCgRwb3J0GAMgASgF", - "EhEKCWF1dGhfbW9kZRgEIAEoCRIUCgxmcm9tX2FkZHJlc3MYBSABKAkSEAoI", - "dXNlcm5hbWUYBiABKAkSEAoIcGFzc3dvcmQYByABKAkSFAoMb2F1dGhfY29u", - "ZmlnGAggASgJImEKG1NoYXJlZFNjcmlwdEFydGlmYWN0TGlzdER0bxJCCgVp", - "dGVtcxgBIAMoCzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNoYXJl", - "ZFNjcmlwdEFydGlmYWN0RHRvImUKHUV4dGVybmFsU3lzdGVtQXJ0aWZhY3RM", - "aXN0RHRvEkQKBWl0ZW1zGAEgAygLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", - "bmQudjEuRXh0ZXJuYWxTeXN0ZW1BcnRpZmFjdER0byJtCiFEYXRhYmFzZUNv", - "bm5lY3Rpb25BcnRpZmFjdExpc3REdG8SSAoFaXRlbXMYASADKAsyOS5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5EYXRhYmFzZUNvbm5lY3Rpb25BcnRp", - "ZmFjdER0byJpCh9Ob3RpZmljYXRpb25MaXN0QXJ0aWZhY3RMaXN0RHRvEkYK", - "BWl0ZW1zGAEgAygLMjcuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTm90", - "aWZpY2F0aW9uTGlzdEFydGlmYWN0RHRvImUKHURhdGFDb25uZWN0aW9uQXJ0", - "aWZhY3RMaXN0RHRvEkQKBWl0ZW1zGAEgAygLMjUuc2NhZGFicmlkZ2Uuc2l0", - "ZWNvbW1hbmQudjEuRGF0YUNvbm5lY3Rpb25BcnRpZmFjdER0byJrCiBTbXRw", - "Q29uZmlndXJhdGlvbkFydGlmYWN0TGlzdER0bxJHCgVpdGVtcxgBIAMoCzI4", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNtdHBDb25maWd1cmF0aW9u", - "QXJ0aWZhY3REdG8i7QQKGURlcGxveUFydGlmYWN0c0NvbW1hbmREdG8SFQoN", - "ZGVwbG95bWVudF9pZBgBIAEoCRJPCg5zaGFyZWRfc2NyaXB0cxgCIAEoCzI3", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNoYXJlZFNjcmlwdEFydGlm", - "YWN0TGlzdER0bxJTChBleHRlcm5hbF9zeXN0ZW1zGAMgASgLMjkuc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXh0ZXJuYWxTeXN0ZW1BcnRpZmFjdExp", - "c3REdG8SWwoUZGF0YWJhc2VfY29ubmVjdGlvbnMYBCABKAsyPS5zY2FkYWJy", - "aWRnZS5zaXRlY29tbWFuZC52MS5EYXRhYmFzZUNvbm5lY3Rpb25BcnRpZmFj", - "dExpc3REdG8SVwoSbm90aWZpY2F0aW9uX2xpc3RzGAUgASgLMjsuc2NhZGFi", + "aW9uc19qc29uGAUgASgJEhcKD3RpbWVvdXRfc2Vjb25kcxgGIAEoBRITCgtt", + "YXhfcmV0cmllcxgHIAEoBRIuCgtyZXRyeV9kZWxheRgIIAEoCzIZLmdvb2ds", + "ZS5wcm90b2J1Zi5EdXJhdGlvbiKNAQodRGF0YWJhc2VDb25uZWN0aW9uQXJ0", + "aWZhY3REdG8SDAoEbmFtZRgBIAEoCRIZChFjb25uZWN0aW9uX3N0cmluZxgC", + "IAEoCRITCgttYXhfcmV0cmllcxgDIAEoBRIuCgtyZXRyeV9kZWxheRgEIAEo", + "CzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbiJFChtOb3RpZmljYXRpb25M", + "aXN0QXJ0aWZhY3REdG8SDAoEbmFtZRgBIAEoCRIYChByZWNpcGllbnRfZW1h", + "aWxzGAIgAygJIqABChlEYXRhQ29ubmVjdGlvbkFydGlmYWN0RHRvEgwKBG5h", + "bWUYASABKAkSEAoIcHJvdG9jb2wYAiABKAkSIgoacHJpbWFyeV9jb25maWd1", + "cmF0aW9uX2pzb24YAyABKAkSIQoZYmFja3VwX2NvbmZpZ3VyYXRpb25fanNv", + "bhgEIAEoCRIcChRmYWlsb3Zlcl9yZXRyeV9jb3VudBgFIAEoBSKtAQocU210", + "cENvbmZpZ3VyYXRpb25BcnRpZmFjdER0bxIMCgRuYW1lGAEgASgJEg4KBnNl", + "cnZlchgCIAEoCRIMCgRwb3J0GAMgASgFEhEKCWF1dGhfbW9kZRgEIAEoCRIU", + "Cgxmcm9tX2FkZHJlc3MYBSABKAkSEAoIdXNlcm5hbWUYBiABKAkSEAoIcGFz", + "c3dvcmQYByABKAkSFAoMb2F1dGhfY29uZmlnGAggASgJImEKG1NoYXJlZFNj", + "cmlwdEFydGlmYWN0TGlzdER0bxJCCgVpdGVtcxgBIAMoCzIzLnNjYWRhYnJp", + "ZGdlLnNpdGVjb21tYW5kLnYxLlNoYXJlZFNjcmlwdEFydGlmYWN0RHRvImUK", + "HUV4dGVybmFsU3lzdGVtQXJ0aWZhY3RMaXN0RHRvEkQKBWl0ZW1zGAEgAygL", + "MjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXh0ZXJuYWxTeXN0ZW1B", + "cnRpZmFjdER0byJtCiFEYXRhYmFzZUNvbm5lY3Rpb25BcnRpZmFjdExpc3RE", + "dG8SSAoFaXRlbXMYASADKAsyOS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5EYXRhYmFzZUNvbm5lY3Rpb25BcnRpZmFjdER0byJpCh9Ob3RpZmljYXRp", + "b25MaXN0QXJ0aWZhY3RMaXN0RHRvEkYKBWl0ZW1zGAEgAygLMjcuc2NhZGFi", "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTm90aWZpY2F0aW9uTGlzdEFydGlmYWN0", - "TGlzdER0bxJTChBkYXRhX2Nvbm5lY3Rpb25zGAYgASgLMjkuc2NhZGFicmlk", - "Z2Uuc2l0ZWNvbW1hbmQudjEuRGF0YUNvbm5lY3Rpb25BcnRpZmFjdExpc3RE", - "dG8SWQoTc210cF9jb25maWd1cmF0aW9ucxgHIAEoCzI8LnNjYWRhYnJpZGdl", - "LnNpdGVjb21tYW5kLnYxLlNtdHBDb25maWd1cmF0aW9uQXJ0aWZhY3RMaXN0", - "RHRvEi0KCXRpbWVzdGFtcBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l", - "c3RhbXAi2QEKG0RlcGxveW1lbnRTdGF0dXNSZXNwb25zZUR0bxIVCg1kZXBs", - "b3ltZW50X2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJ", - "Ej8KBnN0YXR1cxgDIAEoDjIvLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx", - "LkRlcGxveW1lbnRTdGF0dXNEdG8SFQoNZXJyb3JfbWVzc2FnZRgEIAEoCRIt", - "Cgl0aW1lc3RhbXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w", - "IqcBChxJbnN0YW5jZUxpZmVjeWNsZVJlc3BvbnNlRHRvEhIKCmNvbW1hbmRf", - "aWQYASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiABKAkSDwoHc3Vj", + "RHRvImUKHURhdGFDb25uZWN0aW9uQXJ0aWZhY3RMaXN0RHRvEkQKBWl0ZW1z", + "GAEgAygLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGF0YUNvbm5l", + "Y3Rpb25BcnRpZmFjdER0byJrCiBTbXRwQ29uZmlndXJhdGlvbkFydGlmYWN0", + "TGlzdER0bxJHCgVpdGVtcxgBIAMoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21t", + "YW5kLnYxLlNtdHBDb25maWd1cmF0aW9uQXJ0aWZhY3REdG8i7QQKGURlcGxv", + "eUFydGlmYWN0c0NvbW1hbmREdG8SFQoNZGVwbG95bWVudF9pZBgBIAEoCRJP", + "Cg5zaGFyZWRfc2NyaXB0cxgCIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21t", + "YW5kLnYxLlNoYXJlZFNjcmlwdEFydGlmYWN0TGlzdER0bxJTChBleHRlcm5h", + "bF9zeXN0ZW1zGAMgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "RXh0ZXJuYWxTeXN0ZW1BcnRpZmFjdExpc3REdG8SWwoUZGF0YWJhc2VfY29u", + "bmVjdGlvbnMYBCABKAsyPS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5E", + "YXRhYmFzZUNvbm5lY3Rpb25BcnRpZmFjdExpc3REdG8SVwoSbm90aWZpY2F0", + "aW9uX2xpc3RzGAUgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "Tm90aWZpY2F0aW9uTGlzdEFydGlmYWN0TGlzdER0bxJTChBkYXRhX2Nvbm5l", + "Y3Rpb25zGAYgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGF0", + "YUNvbm5lY3Rpb25BcnRpZmFjdExpc3REdG8SWQoTc210cF9jb25maWd1cmF0", + "aW9ucxgHIAEoCzI8LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNtdHBD", + "b25maWd1cmF0aW9uQXJ0aWZhY3RMaXN0RHRvEi0KCXRpbWVzdGFtcBgIIAEo", + "CzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAi2QEKG0RlcGxveW1lbnRT", + "dGF0dXNSZXNwb25zZUR0bxIVCg1kZXBsb3ltZW50X2lkGAEgASgJEhwKFGlu", + "c3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEj8KBnN0YXR1cxgDIAEoDjIvLnNj", + "YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxveW1lbnRTdGF0dXNEdG8S", + "FQoNZXJyb3JfbWVzc2FnZRgEIAEoCRItCgl0aW1lc3RhbXAYBSABKAsyGi5n", + "b29nbGUucHJvdG9idWYuVGltZXN0YW1wIqcBChxJbnN0YW5jZUxpZmVjeWNs", + "ZVJlc3BvbnNlRHRvEhIKCmNvbW1hbmRfaWQYASABKAkSHAoUaW5zdGFuY2Vf", + "dW5pcXVlX25hbWUYAiABKAkSDwoHc3VjY2VzcxgDIAEoCBIVCg1lcnJvcl9t", + "ZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXAi2QEKH0RlcGxveW1lbnRTdGF0ZVF1ZXJ5UmVzcG9u", + "c2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFuY2VfdW5p", + "cXVlX25hbWUYAiABKAkSEwoLaXNfZGVwbG95ZWQYAyABKAgSHQoVYXBwbGll", + "ZF9kZXBsb3ltZW50X2lkGAQgASgJEh0KFWFwcGxpZWRfcmV2aXNpb25faGFz", + "aBgFIAEoCRItCgl0aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYu", + "VGltZXN0YW1wIp4BCh1BcnRpZmFjdERlcGxveW1lbnRSZXNwb25zZUR0bxIV", + "Cg1kZXBsb3ltZW50X2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSDwoHc3Vj", "Y2VzcxgDIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFt", - "cBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAi2QEKH0RlcGxv", - "eW1lbnRTdGF0ZVF1ZXJ5UmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQY", - "ASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiABKAkSEwoLaXNfZGVw", - "bG95ZWQYAyABKAgSHQoVYXBwbGllZF9kZXBsb3ltZW50X2lkGAQgASgJEh0K", - "FWFwcGxpZWRfcmV2aXNpb25faGFzaBgFIAEoCRItCgl0aW1lc3RhbXAYBiAB", - "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIp4BCh1BcnRpZmFjdERl", - "cGxveW1lbnRSZXNwb25zZUR0bxIVCg1kZXBsb3ltZW50X2lkGAEgASgJEg8K", - "B3NpdGVfaWQYAiABKAkSDwoHc3VjY2VzcxgDIAEoCBIVCg1lcnJvcl9tZXNz", - "YWdlGAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1", - "Zi5UaW1lc3RhbXAimgQKEExpZmVjeWNsZVJlcXVlc3QSVQoScmVmcmVzaF9k", - "ZXBsb3ltZW50GAEgASgLMjcuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "UmVmcmVzaERlcGxveW1lbnRDb21tYW5kRHRvSAASTwoPZW5hYmxlX2luc3Rh", - "bmNlGAIgASgLMjQuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRW5hYmxl", - "SW5zdGFuY2VDb21tYW5kRHRvSAASUQoQZGlzYWJsZV9pbnN0YW5jZRgDIAEo", - "CzI1LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRpc2FibGVJbnN0YW5j", - "ZUNvbW1hbmREdG9IABJPCg9kZWxldGVfaW5zdGFuY2UYBCABKAsyNC5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5EZWxldGVJbnN0YW5jZUNvbW1hbmRE", - "dG9IABJcChZkZXBsb3ltZW50X3N0YXRlX3F1ZXJ5GAUgASgLMjouc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVwbG95bWVudFN0YXRlUXVlcnlSZXF1", - "ZXN0RHRvSAASUQoQZGVwbG95X2FydGlmYWN0cxgGIAEoCzI1LnNjYWRhYnJp", - "ZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxveUFydGlmYWN0c0NvbW1hbmREdG9I", - "AEIJCgdjb21tYW5kIoADCg5MaWZlY3ljbGVSZXBseRJUChFkZXBsb3ltZW50", - "X3N0YXR1cxgBIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRl", - "cGxveW1lbnRTdGF0dXNSZXNwb25zZUR0b0gAElYKEmluc3RhbmNlX2xpZmVj", - "eWNsZRgCIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkluc3Rh", - "bmNlTGlmZWN5Y2xlUmVzcG9uc2VEdG9IABJdChZkZXBsb3ltZW50X3N0YXRl", - "X3F1ZXJ5GAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVw", - "bG95bWVudFN0YXRlUXVlcnlSZXNwb25zZUR0b0gAElgKE2FydGlmYWN0X2Rl", - "cGxveW1lbnQYBCABKAsyOS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5B", - "cnRpZmFjdERlcGxveW1lbnRSZXNwb25zZUR0b0gAQgcKBXJlcGx5InwKFEJy", - "b3dzZU5vZGVDb21tYW5kRHRvEhcKD2Nvbm5lY3Rpb25fbmFtZRgBIAEoCRIW", - "Cg5wYXJlbnRfbm9kZV9pZBgCIAEoCRIaChJjb250aW51YXRpb25fdG9rZW4Y", - "AyABKAkSFwoPc2l0ZV9pZGVudGlmaWVyGAQgASgJIoICCg1Ccm93c2VOb2Rl", - "RHRvEg8KB25vZGVfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEkIK", - "Cm5vZGVfY2xhc3MYAyABKA4yLi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", - "MS5Ccm93c2VOb2RlQ2xhc3NEdG8SFAoMaGFzX2NoaWxkcmVuGAQgASgIEhEK", - "CWRhdGFfdHlwZRgFIAEoCRIvCgp2YWx1ZV9yYW5rGAYgASgLMhsuZ29vZ2xl", - "LnByb3RvYnVmLkludDMyVmFsdWUSLAoId3JpdGFibGUYByABKAsyGi5nb29n", - "bGUucHJvdG9idWYuQm9vbFZhbHVlImMKEEJyb3dzZUZhaWx1cmVEdG8SPgoE", - "a2luZBgBIAEoDjIwLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkJyb3dz", - "ZUZhaWx1cmVLaW5kRHRvEg8KB21lc3NhZ2UYAiABKAkiwAEKE0Jyb3dzZU5v", - "ZGVSZXN1bHREdG8SOwoIY2hpbGRyZW4YASADKAsyKS5zY2FkYWJyaWRnZS5z", - "aXRlY29tbWFuZC52MS5Ccm93c2VOb2RlRHRvEhEKCXRydW5jYXRlZBgCIAEo", - "CBI9CgdmYWlsdXJlGAMgASgLMiwuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", - "djEuQnJvd3NlRmFpbHVyZUR0bxIaChJjb250aW51YXRpb25fdG9rZW4YBCAB", - "KAkihwEKHFNlYXJjaEFkZHJlc3NTcGFjZUNvbW1hbmREdG8SFwoPY29ubmVj", - "dGlvbl9uYW1lGAEgASgJEg0KBXF1ZXJ5GAIgASgJEhEKCW1heF9kZXB0aBgD", - "IAEoBRITCgttYXhfcmVzdWx0cxgEIAEoBRIXCg9zaXRlX2lkZW50aWZpZXIY", - "BSABKAkiXQoUQWRkcmVzc1NwYWNlTWF0Y2hEdG8SNwoEbm9kZRgBIAEoCzIp", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkJyb3dzZU5vZGVEdG8SDAoE", - "cGF0aBgCIAEoCSK0AQobU2VhcmNoQWRkcmVzc1NwYWNlUmVzdWx0RHRvEkEK", - "B21hdGNoZXMYASADKAsyMC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5B", - "ZGRyZXNzU3BhY2VNYXRjaER0bxITCgtjYXBfcmVhY2hlZBgCIAEoCBI9Cgdm", - "YWlsdXJlGAMgASgLMiwuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJv", - "d3NlRmFpbHVyZUR0byJFChdSZWFkVGFnVmFsdWVzQ29tbWFuZER0bxIXCg9j", - "b25uZWN0aW9uX25hbWUYASABKAkSEQoJdGFnX3BhdGhzGAIgAygJIsQBChFU", - "YWdSZWFkT3V0Y29tZUR0bxIQCgh0YWdfcGF0aBgBIAEoCRIPCgdzdWNjZXNz", - "GAIgASgIEjUKBXZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", - "bmQudjEuTG9vc2VWYWx1ZRIPCgdxdWFsaXR5GAQgASgJEi0KCXRpbWVzdGFt", - "cBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASFQoNZXJyb3Jf", - "bWVzc2FnZRgGIAEoCSJxChdSZWFkVGFnVmFsdWVzRmFpbHVyZUR0bxJFCgRr", - "aW5kGAEgASgOMjcuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVhZFRh", - "Z1ZhbHVlc0ZhaWx1cmVLaW5kRHRvEg8KB21lc3NhZ2UYAiABKAkinwEKFlJl", - "YWRUYWdWYWx1ZXNSZXN1bHREdG8SPwoIb3V0Y29tZXMYASADKAsyLS5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5UYWdSZWFkT3V0Y29tZUR0bxJECgdm", - "YWlsdXJlGAIgASgLMjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVh", - "ZFRhZ1ZhbHVlc0ZhaWx1cmVEdG8icwoYVmVyaWZ5RW5kcG9pbnRDb21tYW5k", - "RHRvEhcKD2Nvbm5lY3Rpb25fbmFtZRgBIAEoCRIQCghwcm90b2NvbBgCIAEo", - "CRITCgtjb25maWdfanNvbhgDIAEoCRIXCg9zaXRlX2lkZW50aWZpZXIYBCAB", - "KAkiwwEKEVNlcnZlckNlcnRJbmZvRHRvEhIKCnRodW1icHJpbnQYASABKAkS", - "DwoHc3ViamVjdBgCIAEoCRIOCgZpc3N1ZXIYAyABKAkSMgoObm90X2JlZm9y", - "ZV91dGMYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjEKDW5v", - "dF9hZnRlcl91dGMYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w", - "EhIKCmRlcl9iYXNlNjQYBiABKAkiWQoWVmVyaWZ5RmFpbHVyZUtpbmRWYWx1", - "ZRI/CgV2YWx1ZRgBIAEoDjIwLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx", - "LlZlcmlmeUZhaWx1cmVLaW5kRHRvIsABChdWZXJpZnlFbmRwb2ludFJlc3Vs", - "dER0bxIPCgdzdWNjZXNzGAEgASgIEkgKDGZhaWx1cmVfa2luZBgCIAEoCzIy", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlZlcmlmeUZhaWx1cmVLaW5k", - "VmFsdWUSDQoFZXJyb3IYAyABKAkSOwoEY2VydBgEIAEoCzItLnNjYWRhYnJp", - "ZGdlLnNpdGVjb21tYW5kLnYxLlNlcnZlckNlcnRJbmZvRHRvInUKGVRydXN0", - "U2VydmVyQ2VydENvbW1hbmREdG8SFwoPY29ubmVjdGlvbl9uYW1lGAEgASgJ", - "EhIKCmRlcl9iYXNlNjQYAiABKAkSEgoKdGh1bWJwcmludBgDIAEoCRIXCg9z", - "aXRlX2lkZW50aWZpZXIYBCABKAkiNAoZTGlzdFNlcnZlckNlcnRzQ29tbWFu", - "ZER0bxIXCg9zaXRlX2lkZW50aWZpZXIYASABKAkiSQoaUmVtb3ZlU2VydmVy", - "Q2VydENvbW1hbmREdG8SEgoKdGh1bWJwcmludBgBIAEoCRIXCg9zaXRlX2lk", - "ZW50aWZpZXIYAiABKAkiwgEKElRydXN0ZWRDZXJ0SW5mb0R0bxISCgp0aHVt", - "YnByaW50GAEgASgJEg8KB3N1YmplY3QYAiABKAkSDgoGaXNzdWVyGAMgASgJ", - "EjIKDm5vdF9iZWZvcmVfdXRjGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp", - "bWVzdGFtcBIxCg1ub3RfYWZ0ZXJfdXRjGAUgASgLMhouZ29vZ2xlLnByb3Rv", - "YnVmLlRpbWVzdGFtcBIQCghyZWplY3RlZBgGIAEoCCJXChZUcnVzdGVkQ2Vy", - "dEluZm9MaXN0RHRvEj0KBWl0ZW1zGAEgAygLMi4uc2NhZGFicmlkZ2Uuc2l0", - "ZWNvbW1hbmQudjEuVHJ1c3RlZENlcnRJbmZvRHRvIncKEkNlcnRUcnVzdFJl", - "c3VsdER0bxIPCgdzdWNjZXNzGAEgASgIEg0KBWVycm9yGAIgASgJEkEKBWNl", - "cnRzGAMgASgLMjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJ1c3Rl", - "ZENlcnRJbmZvTGlzdER0byK9AQoSV3JpdGVUYWdSZXF1ZXN0RHRvEhYKDmNv", - "cnJlbGF0aW9uX2lkGAEgASgJEhcKD2Nvbm5lY3Rpb25fbmFtZRgCIAEoCRIQ", - "Cgh0YWdfcGF0aBgDIAEoCRI1CgV2YWx1ZRgEIAEoCzImLnNjYWRhYnJpZGdl", - "LnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWUSLQoJdGltZXN0YW1wGAUgASgL", - "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKEAQoTV3JpdGVUYWdSZXNw", - "b25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzdWNjZXNzGAIg", - "ASgIEhUKDWVycm9yX21lc3NhZ2UYAyABKAkSLQoJdGltZXN0YW1wGAQgASgL", - "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKgBQoMT3BjVWFSZXF1ZXN0", - "EkcKC2Jyb3dzZV9ub2RlGAEgASgLMjAuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", - "bmQudjEuQnJvd3NlTm9kZUNvbW1hbmREdG9IABJYChRzZWFyY2hfYWRkcmVz", - "c19zcGFjZRgCIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNl", - "YXJjaEFkZHJlc3NTcGFjZUNvbW1hbmREdG9IABJOCg9yZWFkX3RhZ192YWx1", - "ZXMYAyABKAsyMy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5SZWFkVGFn", - "VmFsdWVzQ29tbWFuZER0b0gAEk8KD3ZlcmlmeV9lbmRwb2ludBgEIAEoCzI0", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlZlcmlmeUVuZHBvaW50Q29t", - "bWFuZER0b0gAElIKEXRydXN0X3NlcnZlcl9jZXJ0GAUgASgLMjUuc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJ1c3RTZXJ2ZXJDZXJ0Q29tbWFuZER0", - "b0gAElIKEWxpc3Rfc2VydmVyX2NlcnRzGAYgASgLMjUuc2NhZGFicmlkZ2Uu", - "c2l0ZWNvbW1hbmQudjEuTGlzdFNlcnZlckNlcnRzQ29tbWFuZER0b0gAElQK", - "EnJlbW92ZV9zZXJ2ZXJfY2VydBgHIAEoCzI2LnNjYWRhYnJpZGdlLnNpdGVj", - "b21tYW5kLnYxLlJlbW92ZVNlcnZlckNlcnRDb21tYW5kRHRvSAASQwoJd3Jp", - "dGVfdGFnGAggASgLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuV3Jp", - "dGVUYWdSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCLhAwoKT3BjVWFSZXBseRJG", - "Cgticm93c2Vfbm9kZRgBIAEoCzIvLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k", - "LnYxLkJyb3dzZU5vZGVSZXN1bHREdG9IABJXChRzZWFyY2hfYWRkcmVzc19z", - "cGFjZRgCIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNlYXJj", - "aEFkZHJlc3NTcGFjZVJlc3VsdER0b0gAEk0KD3JlYWRfdGFnX3ZhbHVlcxgD", - "IAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJlYWRUYWdWYWx1", - "ZXNSZXN1bHREdG9IABJOCg92ZXJpZnlfZW5kcG9pbnQYBCABKAsyMy5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5WZXJpZnlFbmRwb2ludFJlc3VsdER0", - "b0gAEkQKCmNlcnRfdHJ1c3QYBSABKAsyLi5zY2FkYWJyaWRnZS5zaXRlY29t", - "bWFuZC52MS5DZXJ0VHJ1c3RSZXN1bHREdG9IABJECgl3cml0ZV90YWcYBiAB", - "KAsyLy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Xcml0ZVRhZ1Jlc3Bv", - "bnNlRHRvSABCBwoFcmVwbHkixQIKF0V2ZW50TG9nUXVlcnlSZXF1ZXN0RHRv", - "EhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSKAoE", - "ZnJvbRgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASJgoCdG8Y", - "BCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhIKCmV2ZW50X3R5", - "cGUYBSABKAkSEAoIc2V2ZXJpdHkYBiABKAkSEwoLaW5zdGFuY2VfaWQYByAB", - "KAkSFgoOa2V5d29yZF9maWx0ZXIYCCABKAkSGgoSY29udGludWF0aW9uX3Rv", - "a2VuGAkgASgJEhEKCXBhZ2Vfc2l6ZRgKIAEoBRItCgl0aW1lc3RhbXAYCyAB", - "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIroBChBFdmVudExvZ0Vu", - "dHJ5RHRvEgoKAmlkGAEgASgJEi0KCXRpbWVzdGFtcBgCIAEoCzIaLmdvb2ds", - "ZS5wcm90b2J1Zi5UaW1lc3RhbXASEgoKZXZlbnRfdHlwZRgDIAEoCRIQCghz", - "ZXZlcml0eRgEIAEoCRITCgtpbnN0YW5jZV9pZBgFIAEoCRIOCgZzb3VyY2UY", - "BiABKAkSDwoHbWVzc2FnZRgHIAEoCRIPCgdkZXRhaWxzGAggASgJIocCChhF", - "dmVudExvZ1F1ZXJ5UmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASAB", - "KAkSDwoHc2l0ZV9pZBgCIAEoCRI9CgdlbnRyaWVzGAMgAygLMiwuc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRMb2dFbnRyeUR0bxIaChJjb250", - "aW51YXRpb25fdG9rZW4YBCABKAkSEAoIaGFzX21vcmUYBSABKAgSDwoHc3Vj", - "Y2VzcxgGIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAcgASgJEi0KCXRpbWVzdGFt", - "cBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiZAoXRGVidWdT", - "bmFwc2hvdFJlcXVlc3REdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASAB", - "KAkSFgoOY29ycmVsYXRpb25faWQYAiABKAkSEwoLYWxhcm1zX29ubHkYAyAB", - "KAgiVAocU3Vic2NyaWJlRGVidWdWaWV3UmVxdWVzdER0bxIcChRpbnN0YW5j", - "ZV91bmlxdWVfbmFtZRgBIAEoCRIWCg5jb3JyZWxhdGlvbl9pZBgCIAEoCSJW", - "Ch5VbnN1YnNjcmliZURlYnVnVmlld1JlcXVlc3REdG8SHAoUaW5zdGFuY2Vf", - "dW5pcXVlX25hbWUYASABKAkSFgoOY29ycmVsYXRpb25faWQYAiABKAkiHAoa", - "VW5zdWJzY3JpYmVEZWJ1Z1ZpZXdBY2tEdG8i1AEKFkFsYXJtQ29uZGl0aW9u", - "U3RhdGVEdG8SDgoGYWN0aXZlGAEgASgIEhQKDGFja25vd2xlZGdlZBgCIAEo", - "CBItCgljb25maXJtZWQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZh", - "bHVlEj8KBnNoZWx2ZRgEIAEoDjIvLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k", - "LnYxLkFsYXJtU2hlbHZlU3RhdGVEdG8SEgoKc3VwcHJlc3NlZBgFIAEoCBIQ", - "CghzZXZlcml0eRgGIAEoBSLdAQoWRGVidWdBdHRyaWJ1dGVWYWx1ZUR0bxIc", - "ChRpbnN0YW5jZV91bmlxdWVfbmFtZRgBIAEoCRIWCg5hdHRyaWJ1dGVfcGF0", - "aBgCIAEoCRIWCg5hdHRyaWJ1dGVfbmFtZRgDIAEoCRI1CgV2YWx1ZRgEIAEo", - "CzImLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWUSDwoH", - "cXVhbGl0eRgFIAEoCRItCgl0aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJv", - "dG9idWYuVGltZXN0YW1wIq8FChJEZWJ1Z0FsYXJtU3RhdGVEdG8SHAoUaW5z", - "dGFuY2VfdW5pcXVlX25hbWUYASABKAkSEgoKYWxhcm1fbmFtZRgCIAEoCRI4", - "CgVzdGF0ZRgDIAEoDjIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkFs", - "YXJtU3RhdGVEdG8SEAoIcHJpb3JpdHkYBCABKAUSLQoJdGltZXN0YW1wGAUg", - "ASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI4CgVsZXZlbBgGIAEo", - "DjIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtTGV2ZWxEdG8S", - "DwoHbWVzc2FnZRgHIAEoCRI2CgRraW5kGAggASgOMiguc2NhZGFicmlkZ2Uu", - "c2l0ZWNvbW1hbmQudjEuQWxhcm1LaW5kRHRvEkUKCWNvbmRpdGlvbhgJIAEo", - "CzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtQ29uZGl0aW9u", - "U3RhdGVEdG8SGAoQc291cmNlX3JlZmVyZW5jZRgKIAEoCRIXCg9hbGFybV90", - "eXBlX25hbWUYCyABKAkSEAoIY2F0ZWdvcnkYDCABKAkSFQoNb3BlcmF0b3Jf", - "dXNlchgNIAEoCRIYChBvcGVyYXRvcl9jb21tZW50GA4gASgJEjcKE29yaWdp", - "bmFsX3JhaXNlX3RpbWUYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0", - "YW1wEhUKDWN1cnJlbnRfdmFsdWUYECABKAkSEwoLbGltaXRfdmFsdWUYESAB", - "KAkSJAocbmF0aXZlX3NvdXJjZV9jYW5vbmljYWxfbmFtZRgSIAEoCRIhChlp", - "c19jb25maWd1cmVkX3BsYWNlaG9sZGVyGBMgASgIIpwCChREZWJ1Z1ZpZXdT", - "bmFwc2hvdER0bxIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgBIAEoCRJMChBh", - "dHRyaWJ1dGVfdmFsdWVzGAIgAygLMjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", - "bmQudjEuRGVidWdBdHRyaWJ1dGVWYWx1ZUR0bxJECgxhbGFybV9zdGF0ZXMY", - "AyADKAsyLi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5EZWJ1Z0FsYXJt", - "U3RhdGVEdG8SNgoSc25hcHNob3RfdGltZXN0YW1wGAQgASgLMhouZ29vZ2xl", - "LnByb3RvYnVmLlRpbWVzdGFtcBIaChJpbnN0YW5jZV9ub3RfZm91bmQYBSAB", - "KAgi8AIKDFF1ZXJ5UmVxdWVzdBJOCg9ldmVudF9sb2dfcXVlcnkYASABKAsy", - "My5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5FdmVudExvZ1F1ZXJ5UmVx", - "dWVzdER0b0gAEk0KDmRlYnVnX3NuYXBzaG90GAIgASgLMjMuc2NhZGFicmlk", - "Z2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdTbmFwc2hvdFJlcXVlc3REdG9IABJY", - "ChRzdWJzY3JpYmVfZGVidWdfdmlldxgDIAEoCzI4LnNjYWRhYnJpZGdlLnNp", - "dGVjb21tYW5kLnYxLlN1YnNjcmliZURlYnVnVmlld1JlcXVlc3REdG9IABJc", - "ChZ1bnN1YnNjcmliZV9kZWJ1Z192aWV3GAQgASgLMjouc2NhZGFicmlkZ2Uu", - "c2l0ZWNvbW1hbmQudjEuVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRv", - "SABCCQoHY29tbWFuZCKRAgoKUXVlcnlSZXBseRJPCg9ldmVudF9sb2dfcXVl", - "cnkYASABKAsyNC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5FdmVudExv", - "Z1F1ZXJ5UmVzcG9uc2VEdG9IABJPChNkZWJ1Z192aWV3X3NuYXBzaG90GAIg", - "ASgLMjAuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdWaWV3U25h", - "cHNob3REdG9IABJYChZ1bnN1YnNjcmliZV9kZWJ1Z192aWV3GAMgASgLMjYu", - "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVW5zdWJzY3JpYmVEZWJ1Z1Zp", - "ZXdBY2tEdG9IAEIHCgVyZXBseSKeAQocUGFya2VkTWVzc2FnZVF1ZXJ5UmVx", - "dWVzdER0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzaXRlX2lkGAIg", - "ASgJEhMKC3BhZ2VfbnVtYmVyGAMgASgFEhEKCXBhZ2Vfc2l6ZRgEIAEoBRIt", - "Cgl0aW1lc3RhbXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w", - "IvICChVQYXJrZWRNZXNzYWdlRW50cnlEdG8SEgoKbWVzc2FnZV9pZBgBIAEo", - "CRIVCg10YXJnZXRfc3lzdGVtGAIgASgJEhMKC21ldGhvZF9uYW1lGAMgASgJ", - "EhUKDWVycm9yX21lc3NhZ2UYBCABKAkSFQoNYXR0ZW1wdF9jb3VudBgFIAEo", - "BRI2ChJvcmlnaW5hbF90aW1lc3RhbXAYBiABKAsyGi5nb29nbGUucHJvdG9i", - "dWYuVGltZXN0YW1wEjoKFmxhc3RfYXR0ZW1wdF90aW1lc3RhbXAYByABKAsy", - "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhQKDG1heF9hdHRlbXB0cxgI", - "IAEoBRJICghjYXRlZ29yeRgJIAEoDjI2LnNjYWRhYnJpZGdlLnNpdGVjb21t", - "YW5kLnYxLlN0b3JlQW5kRm9yd2FyZENhdGVnb3J5RHRvEhcKD29yaWdpbl9p", - "bnN0YW5jZRgKIAEoCSKhAgodUGFya2VkTWVzc2FnZVF1ZXJ5UmVzcG9uc2VE", - "dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRJD", - "CghtZXNzYWdlcxgDIAMoCzIxLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx", - "LlBhcmtlZE1lc3NhZ2VFbnRyeUR0bxITCgt0b3RhbF9jb3VudBgEIAEoBRIT", - "CgtwYWdlX251bWJlchgFIAEoBRIRCglwYWdlX3NpemUYBiABKAUSDwoHc3Vj", - "Y2VzcxgHIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAggASgJEi0KCXRpbWVzdGFt", - "cBgJIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiigEKHFBhcmtl", - "ZE1lc3NhZ2VSZXRyeVJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASAB", - "KAkSDwoHc2l0ZV9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJEi0KCXRp", - "bWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiXwod", - "UGFya2VkTWVzc2FnZVJldHJ5UmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25f", - "aWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMg", - "ASgJIowBCh5QYXJrZWRNZXNzYWdlRGlzY2FyZFJlcXVlc3REdG8SFgoOY29y", - "cmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRISCgptZXNzYWdl", - "X2lkGAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1", - "Zi5UaW1lc3RhbXAiYQofUGFya2VkTWVzc2FnZURpc2NhcmRSZXNwb25zZUR0", - "bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzdWNjZXNzGAIgASgIEhUK", - "DWVycm9yX21lc3NhZ2UYAyABKAkiTwoXUmV0cnlQYXJrZWRPcGVyYXRpb25E", - "dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSHAoUdHJhY2tlZF9vcGVyYXRp", - "b25faWQYAiABKAkiUQoZRGlzY2FyZFBhcmtlZE9wZXJhdGlvbkR0bxIWCg5j", - "b3JyZWxhdGlvbl9pZBgBIAEoCRIcChR0cmFja2VkX29wZXJhdGlvbl9pZBgC", - "IAEoCSJdChtQYXJrZWRPcGVyYXRpb25BY3Rpb25BY2tEdG8SFgoOY29ycmVs", - "YXRpb25faWQYASABKAkSDwoHYXBwbGllZBgCIAEoCBIVCg1lcnJvcl9tZXNz", - "YWdlGAMgASgJIt4DCg1QYXJrZWRSZXF1ZXN0ElgKFHBhcmtlZF9tZXNzYWdl", - "X3F1ZXJ5GAEgASgLMjguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFy", - "a2VkTWVzc2FnZVF1ZXJ5UmVxdWVzdER0b0gAElgKFHBhcmtlZF9tZXNzYWdl", - "X3JldHJ5GAIgASgLMjguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFy", - "a2VkTWVzc2FnZVJldHJ5UmVxdWVzdER0b0gAElwKFnBhcmtlZF9tZXNzYWdl", - "X2Rpc2NhcmQYAyABKAsyOi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Q", - "YXJrZWRNZXNzYWdlRGlzY2FyZFJlcXVlc3REdG9IABJVChZyZXRyeV9wYXJr", - "ZWRfb3BlcmF0aW9uGAQgASgLMjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", - "djEuUmV0cnlQYXJrZWRPcGVyYXRpb25EdG9IABJZChhkaXNjYXJkX3Bhcmtl", - "ZF9vcGVyYXRpb24YBSABKAsyNS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", - "MS5EaXNjYXJkUGFya2VkT3BlcmF0aW9uRHRvSABCCQoHY29tbWFuZCKHAwoL", - "UGFya2VkUmVwbHkSWQoUcGFya2VkX21lc3NhZ2VfcXVlcnkYASABKAsyOS5z", - "Y2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRNZXNzYWdlUXVlcnlS", - "ZXNwb25zZUR0b0gAElkKFHBhcmtlZF9tZXNzYWdlX3JldHJ5GAIgASgLMjku", - "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVJldHJ5", - "UmVzcG9uc2VEdG9IABJdChZwYXJrZWRfbWVzc2FnZV9kaXNjYXJkGAMgASgL", - "Mjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZURp", - "c2NhcmRSZXNwb25zZUR0b0gAEloKF3BhcmtlZF9vcGVyYXRpb25fYWN0aW9u", - "GAQgASgLMjcuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkT3Bl", - "cmF0aW9uQWN0aW9uQWNrRHRvSABCBwoFcmVwbHki7QEKFVJvdXRlVG9DYWxs", - "UmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5j", - "ZV91bmlxdWVfbmFtZRgCIAEoCRITCgtzY3JpcHRfbmFtZRgDIAEoCRI9Cgpw", - "YXJhbWV0ZXJzGAQgASgLMikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "TG9vc2VWYWx1ZU1hcBItCgl0aW1lc3RhbXAYBSABKAsyGi5nb29nbGUucHJv", - "dG9idWYuVGltZXN0YW1wEhsKE3BhcmVudF9leGVjdXRpb25faWQYBiABKAki", - "xQEKFlJvdXRlVG9DYWxsUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQY", - "ASABKAkSDwoHc3VjY2VzcxgCIAEoCBI8CgxyZXR1cm5fdmFsdWUYAyABKAsy", - "Ji5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEhUKDWVy", - "cm9yX21lc3NhZ2UYBCABKAkSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xl", - "LnByb3RvYnVmLlRpbWVzdGFtcCK7AQoeUm91dGVUb0dldEF0dHJpYnV0ZXNS", - "ZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNl", - "X3VuaXF1ZV9uYW1lGAIgASgJEhcKD2F0dHJpYnV0ZV9uYW1lcxgDIAMoCRIt", - "Cgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w", - "EhsKE3BhcmVudF9leGVjdXRpb25faWQYBSABKAkiywEKH1JvdXRlVG9HZXRB", - "dHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkS", - "OQoGdmFsdWVzGAIgASgLMikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "TG9vc2VWYWx1ZU1hcBIPCgdzdWNjZXNzGAMgASgIEhUKDWVycm9yX21lc3Nh", - "Z2UYBCABKAkSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVm", - "LlRpbWVzdGFtcCLFAgoeUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRv", - "EhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9u", - "YW1lGAIgASgJEmkKEGF0dHJpYnV0ZV92YWx1ZXMYAyADKAsyTy5zY2FkYWJy", - "aWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1JlcXVl", - "c3REdG8uQXR0cmlidXRlVmFsdWVzRW50cnkSLQoJdGltZXN0YW1wGAQgASgL", - "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0", - "aW9uX2lkGAUgASgJGjYKFEF0dHJpYnV0ZVZhbHVlc0VudHJ5EgsKA2tleRgB", - "IAEoCRINCgV2YWx1ZRgCIAEoCToCOAEikAEKH1JvdXRlVG9TZXRBdHRyaWJ1", - "dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3Vj", - "Y2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJEi0KCXRpbWVzdGFt", - "cBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiwwIKIVJvdXRl", - "VG9XYWl0Rm9yQXR0cmlidXRlUmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9p", - "ZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRIWCg5hdHRy", - "aWJ1dGVfbmFtZRgDIAEoCRI6ChR0YXJnZXRfdmFsdWVfZW5jb2RlZBgEIAEo", - "CzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRIqCgd0aW1lb3V0GAUg", - "ASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEi0KCXRpbWVzdGFtcBgG", - "IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4", - "ZWN1dGlvbl9pZBgHIAEoCRIcChRyZXF1aXJlX2dvb2RfcXVhbGl0eRgIIAEo", - "CCL/AQoiUm91dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXNwb25zZUR0bxIWCg5j", - "b3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdtYXRjaGVkGAIgASgIEjUKBXZhbHVl", - "GAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1", - "ZRIPCgdxdWFsaXR5GAQgASgJEhEKCXRpbWVkX291dBgFIAEoCBIPCgdzdWNj", - "ZXNzGAYgASgIEhUKDWVycm9yX21lc3NhZ2UYByABKAkSLQoJdGltZXN0YW1w", - "GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKJAwoMUm91dGVS", - "ZXF1ZXN0EkoKDXJvdXRlX3RvX2NhbGwYASABKAsyMS5zY2FkYWJyaWRnZS5z", - "aXRlY29tbWFuZC52MS5Sb3V0ZVRvQ2FsbFJlcXVlc3REdG9IABJdChdyb3V0", - "ZV90b19nZXRfYXR0cmlidXRlcxgCIAEoCzI6LnNjYWRhYnJpZGdlLnNpdGVj", - "b21tYW5kLnYxLlJvdXRlVG9HZXRBdHRyaWJ1dGVzUmVxdWVzdER0b0gAEl0K", - "F3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgLMjouc2NhZGFicmlkZ2Uu", - "c2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRv", - "SAASZAobcm91dGVfdG9fd2FpdF9mb3JfYXR0cmlidXRlGAQgASgLMj0uc2Nh", - "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1dhaXRGb3JBdHRyaWJ1", - "dGVSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKJAwoKUm91dGVSZXBseRJLCg1y", - "b3V0ZV90b19jYWxsGAEgASgLMjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", - "djEuUm91dGVUb0NhbGxSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3RvX2dldF9h", - "dHRyaWJ1dGVzGAIgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "Um91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3Rv", - "X3NldF9hdHRyaWJ1dGVzGAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", - "bmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEmUKG3Jv", - "dXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgEIAEoCzI+LnNjYWRhYnJpZGdl", - "LnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVzcG9u", - "c2VEdG9IAEIHCgVyZXBseSJBChZUcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvEhYK", - "DmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkibQoSU2l0", - "ZUZhaWxvdmVyQWNrRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhAKCGFj", - "Y2VwdGVkGAIgASgIEhYKDnRhcmdldF9hZGRyZXNzGAMgASgJEhUKDWVycm9y", - "X21lc3NhZ2UYBCABKAkqywEKE0RlcGxveW1lbnRTdGF0dXNEdG8SJQohREVQ", - "TE9ZTUVOVF9TVEFUVVNfRFRPX1VOU1BFQ0lGSUVEEAASIQodREVQTE9ZTUVO", - "VF9TVEFUVVNfRFRPX1BFTkRJTkcQARIlCiFERVBMT1lNRU5UX1NUQVRVU19E", - "VE9fSU5fUFJPR1JFU1MQAhIhCh1ERVBMT1lNRU5UX1NUQVRVU19EVE9fU1VD", - "Q0VTUxADEiAKHERFUExPWU1FTlRfU1RBVFVTX0RUT19GQUlMRUQQBCrEAQoS", - "QnJvd3NlTm9kZUNsYXNzRHRvEiUKIUJST1dTRV9OT0RFX0NMQVNTX0RUT19V", - "TlNQRUNJRklFRBAAEiAKHEJST1dTRV9OT0RFX0NMQVNTX0RUT19PQkpFQ1QQ", - "ARIiCh5CUk9XU0VfTk9ERV9DTEFTU19EVE9fVkFSSUFCTEUQAhIgChxCUk9X", - "U0VfTk9ERV9DTEFTU19EVE9fTUVUSE9EEAMSHwobQlJPV1NFX05PREVfQ0xB", - "U1NfRFRPX09USEVSEAQqoQIKFEJyb3dzZUZhaWx1cmVLaW5kRHRvEicKI0JS", - "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASMAosQlJPV1NF", - "X0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfRk9VTkQQARI0CjBC", - "Uk9XU0VfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9DT05ORUNU", - "RUQQAhIpCiVCUk9XU0VfRkFJTFVSRV9LSU5EX0RUT19OT1RfQlJPV1NBQkxF", - "EAMSIwofQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJEJS", - "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKqoCChtSZWFk", - "VGFnVmFsdWVzRmFpbHVyZUtpbmREdG8SMAosUkVBRF9UQUdfVkFMVUVTX0ZB", - "SUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABI5CjVSRUFEX1RBR19WQUxV", - "RVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9GT1VORBABEj0K", - "OVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05f", - "Tk9UX0NPTk5FQ1RFRBACEiwKKFJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJ", - "TkRfRFRPX1RJTUVPVVQQAxIxCi1SRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9L", - "SU5EX0RUT19TRVJWRVJfRVJST1IQBCqTAgoUVmVyaWZ5RmFpbHVyZUtpbmRE", - "dG8SJwojVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABIn", - "CiNWRVJJRllfRkFJTFVSRV9LSU5EX0RUT19VTlJFQUNIQUJMRRABEicKI1ZF", - "UklGWV9GQUlMVVJFX0tJTkRfRFRPX0FVVEhfRkFJTEVEEAISMQotVkVSSUZZ", - "X0ZBSUxVUkVfS0lORF9EVE9fVU5UUlVTVEVEX0NFUlRJRklDQVRFEAMSIwof", - "VkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJFZFUklGWV9G", - "QUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKuUBChpTdG9yZUFuZEZv", - "cndhcmRDYXRlZ29yeUR0bxIuCipTVE9SRV9BTkRfRk9SV0FSRF9DQVRFR09S", - "WV9EVE9fVU5TUEVDSUZJRUQQABIyCi5TVE9SRV9BTkRfRk9SV0FSRF9DQVRF", - "R09SWV9EVE9fRVhURVJOQUxfU1lTVEVNEAESLworU1RPUkVfQU5EX0ZPUldB", - "UkRfQ0FURUdPUllfRFRPX05PVElGSUNBVElPThACEjIKLlNUT1JFX0FORF9G", - "T1JXQVJEX0NBVEVHT1JZX0RUT19DQUNIRURfREJfV1JJVEUQAypoCg1BbGFy", - "bVN0YXRlRHRvEh8KG0FMQVJNX1NUQVRFX0RUT19VTlNQRUNJRklFRBAAEhoK", - "FkFMQVJNX1NUQVRFX0RUT19BQ1RJVkUQARIaChZBTEFSTV9TVEFURV9EVE9f", - "Tk9STUFMEAIquQEKDUFsYXJtTGV2ZWxEdG8SHwobQUxBUk1fTEVWRUxfRFRP", - "X1VOU1BFQ0lGSUVEEAASGAoUQUxBUk1fTEVWRUxfRFRPX05PTkUQARIXChNB", - "TEFSTV9MRVZFTF9EVE9fTE9XEAISGwoXQUxBUk1fTEVWRUxfRFRPX0xPV19M", - "T1cQAxIYChRBTEFSTV9MRVZFTF9EVE9fSElHSBAEEh0KGUFMQVJNX0xFVkVM", - "X0RUT19ISUdIX0hJR0gQBSqSAQoMQWxhcm1LaW5kRHRvEh4KGkFMQVJNX0tJ", - "TkRfRFRPX1VOU1BFQ0lGSUVEEAASGwoXQUxBUk1fS0lORF9EVE9fQ09NUFVU", - "RUQQARIgChxBTEFSTV9LSU5EX0RUT19OQVRJVkVfT1BDX1VBEAISIwofQUxB", - "Uk1fS0lORF9EVE9fTkFUSVZFX01YX0FDQ0VTUxADKugBChNBbGFybVNoZWx2", - "ZVN0YXRlRHRvEiYKIkFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVU5TUEVDSUZJ", - "RUQQABIkCiBBTEFSTV9TSEVMVkVfU1RBVEVfRFRPX1VOU0hFTFZFRBABEisK", - "J0FMQVJNX1NIRUxWRV9TVEFURV9EVE9fT05FX1NIT1RfU0hFTFZFRBACEigK", - "JEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVElNRURfU0hFTFZFRBADEiwKKEFM", - "QVJNX1NIRUxWRV9TVEFURV9EVE9fUEVSTUFORU5UX1NIRUxWRUQQBDKEBQoS", - "U2l0ZUNvbW1hbmRTZXJ2aWNlEmwKEEV4ZWN1dGVMaWZlY3ljbGUSLC5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5MaWZlY3ljbGVSZXF1ZXN0Giouc2Nh", - "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlmZWN5Y2xlUmVwbHkSYAoMRXhl", - "Y3V0ZU9wY1VhEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFS", - "ZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFSZXBs", - "eRJgCgxFeGVjdXRlUXVlcnkSKC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", - "MS5RdWVyeVJlcXVlc3QaJi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5R", - "dWVyeVJlcGx5EmMKDUV4ZWN1dGVQYXJrZWQSKS5zY2FkYWJyaWRnZS5zaXRl", - "Y29tbWFuZC52MS5QYXJrZWRSZXF1ZXN0Gicuc2NhZGFicmlkZ2Uuc2l0ZWNv", - "bW1hbmQudjEuUGFya2VkUmVwbHkSYAoMRXhlY3V0ZVJvdXRlEiguc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXF1ZXN0GiYuc2NhZGFicmlk", - "Z2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXBseRJ1Cg9UcmlnZ2VyRmFpbG92", - "ZXISMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5UcmlnZ2VyU2l0ZUZh", - "aWxvdmVyRHRvGi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuU2l0ZUZh", - "aWxvdmVyQWNrRHRvQiuqAihaQi5NT00uV1cuU2NhZGFCcmlkZ2UuQ29tbXVu", - "aWNhdGlvbi5HcnBjYgZwcm90bzM=")); + "cBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAimgQKEExpZmVj", + "eWNsZVJlcXVlc3QSVQoScmVmcmVzaF9kZXBsb3ltZW50GAEgASgLMjcuc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVmcmVzaERlcGxveW1lbnRDb21t", + "YW5kRHRvSAASTwoPZW5hYmxlX2luc3RhbmNlGAIgASgLMjQuc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuRW5hYmxlSW5zdGFuY2VDb21tYW5kRHRvSAAS", + "UQoQZGlzYWJsZV9pbnN0YW5jZRgDIAEoCzI1LnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLkRpc2FibGVJbnN0YW5jZUNvbW1hbmREdG9IABJPCg9kZWxl", + "dGVfaW5zdGFuY2UYBCABKAsyNC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5EZWxldGVJbnN0YW5jZUNvbW1hbmREdG9IABJcChZkZXBsb3ltZW50X3N0", + "YXRlX3F1ZXJ5GAUgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "RGVwbG95bWVudFN0YXRlUXVlcnlSZXF1ZXN0RHRvSAASUQoQZGVwbG95X2Fy", + "dGlmYWN0cxgGIAEoCzI1LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRl", + "cGxveUFydGlmYWN0c0NvbW1hbmREdG9IAEIJCgdjb21tYW5kIoADCg5MaWZl", + "Y3ljbGVSZXBseRJUChFkZXBsb3ltZW50X3N0YXR1cxgBIAEoCzI3LnNjYWRh", + "YnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlcGxveW1lbnRTdGF0dXNSZXNwb25z", + "ZUR0b0gAElYKEmluc3RhbmNlX2xpZmVjeWNsZRgCIAEoCzI4LnNjYWRhYnJp", + "ZGdlLnNpdGVjb21tYW5kLnYxLkluc3RhbmNlTGlmZWN5Y2xlUmVzcG9uc2VE", + "dG9IABJdChZkZXBsb3ltZW50X3N0YXRlX3F1ZXJ5GAMgASgLMjsuc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVwbG95bWVudFN0YXRlUXVlcnlSZXNw", + "b25zZUR0b0gAElgKE2FydGlmYWN0X2RlcGxveW1lbnQYBCABKAsyOS5zY2Fk", + "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5BcnRpZmFjdERlcGxveW1lbnRSZXNw", + "b25zZUR0b0gAQgcKBXJlcGx5InwKFEJyb3dzZU5vZGVDb21tYW5kRHRvEhcK", + "D2Nvbm5lY3Rpb25fbmFtZRgBIAEoCRIWCg5wYXJlbnRfbm9kZV9pZBgCIAEo", + "CRIaChJjb250aW51YXRpb25fdG9rZW4YAyABKAkSFwoPc2l0ZV9pZGVudGlm", + "aWVyGAQgASgJIoICCg1Ccm93c2VOb2RlRHRvEg8KB25vZGVfaWQYASABKAkS", + "FAoMZGlzcGxheV9uYW1lGAIgASgJEkIKCm5vZGVfY2xhc3MYAyABKA4yLi5z", + "Y2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93c2VOb2RlQ2xhc3NEdG8S", + "FAoMaGFzX2NoaWxkcmVuGAQgASgIEhEKCWRhdGFfdHlwZRgFIAEoCRIvCgp2", + "YWx1ZV9yYW5rGAYgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUS", + "LAoId3JpdGFibGUYByABKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVl", + "ImMKEEJyb3dzZUZhaWx1cmVEdG8SPgoEa2luZBgBIAEoDjIwLnNjYWRhYnJp", + "ZGdlLnNpdGVjb21tYW5kLnYxLkJyb3dzZUZhaWx1cmVLaW5kRHRvEg8KB21l", + "c3NhZ2UYAiABKAkiwAEKE0Jyb3dzZU5vZGVSZXN1bHREdG8SOwoIY2hpbGRy", + "ZW4YASADKAsyKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Ccm93c2VO", + "b2RlRHRvEhEKCXRydW5jYXRlZBgCIAEoCBI9CgdmYWlsdXJlGAMgASgLMiwu", + "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlRmFpbHVyZUR0bxIa", + "ChJjb250aW51YXRpb25fdG9rZW4YBCABKAkihwEKHFNlYXJjaEFkZHJlc3NT", + "cGFjZUNvbW1hbmREdG8SFwoPY29ubmVjdGlvbl9uYW1lGAEgASgJEg0KBXF1", + "ZXJ5GAIgASgJEhEKCW1heF9kZXB0aBgDIAEoBRITCgttYXhfcmVzdWx0cxgE", + "IAEoBRIXCg9zaXRlX2lkZW50aWZpZXIYBSABKAkiXQoUQWRkcmVzc1NwYWNl", + "TWF0Y2hEdG8SNwoEbm9kZRgBIAEoCzIpLnNjYWRhYnJpZGdlLnNpdGVjb21t", + "YW5kLnYxLkJyb3dzZU5vZGVEdG8SDAoEcGF0aBgCIAEoCSK0AQobU2VhcmNo", + "QWRkcmVzc1NwYWNlUmVzdWx0RHRvEkEKB21hdGNoZXMYASADKAsyMC5zY2Fk", + "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5BZGRyZXNzU3BhY2VNYXRjaER0bxIT", + "CgtjYXBfcmVhY2hlZBgCIAEoCBI9CgdmYWlsdXJlGAMgASgLMiwuc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlRmFpbHVyZUR0byJFChdSZWFk", + "VGFnVmFsdWVzQ29tbWFuZER0bxIXCg9jb25uZWN0aW9uX25hbWUYASABKAkS", + "EQoJdGFnX3BhdGhzGAIgAygJIsQBChFUYWdSZWFkT3V0Y29tZUR0bxIQCgh0", + "YWdfcGF0aBgBIAEoCRIPCgdzdWNjZXNzGAIgASgIEjUKBXZhbHVlGAMgASgL", + "MiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZRIPCgdx", + "dWFsaXR5GAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXASFQoNZXJyb3JfbWVzc2FnZRgGIAEoCSJxChdSZWFk", + "VGFnVmFsdWVzRmFpbHVyZUR0bxJFCgRraW5kGAEgASgOMjcuc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuUmVhZFRhZ1ZhbHVlc0ZhaWx1cmVLaW5kRHRv", + "Eg8KB21lc3NhZ2UYAiABKAkinwEKFlJlYWRUYWdWYWx1ZXNSZXN1bHREdG8S", + "PwoIb3V0Y29tZXMYASADKAsyLS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5UYWdSZWFkT3V0Y29tZUR0bxJECgdmYWlsdXJlGAIgASgLMjMuc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmVhZFRhZ1ZhbHVlc0ZhaWx1cmVEdG8i", + "cwoYVmVyaWZ5RW5kcG9pbnRDb21tYW5kRHRvEhcKD2Nvbm5lY3Rpb25fbmFt", + "ZRgBIAEoCRIQCghwcm90b2NvbBgCIAEoCRITCgtjb25maWdfanNvbhgDIAEo", + "CRIXCg9zaXRlX2lkZW50aWZpZXIYBCABKAkiwwEKEVNlcnZlckNlcnRJbmZv", + "RHRvEhIKCnRodW1icHJpbnQYASABKAkSDwoHc3ViamVjdBgCIAEoCRIOCgZp", + "c3N1ZXIYAyABKAkSMgoObm90X2JlZm9yZV91dGMYBCABKAsyGi5nb29nbGUu", + "cHJvdG9idWYuVGltZXN0YW1wEjEKDW5vdF9hZnRlcl91dGMYBSABKAsyGi5n", + "b29nbGUucHJvdG9idWYuVGltZXN0YW1wEhIKCmRlcl9iYXNlNjQYBiABKAki", + "WQoWVmVyaWZ5RmFpbHVyZUtpbmRWYWx1ZRI/CgV2YWx1ZRgBIAEoDjIwLnNj", + "YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlZlcmlmeUZhaWx1cmVLaW5kRHRv", + "IsABChdWZXJpZnlFbmRwb2ludFJlc3VsdER0bxIPCgdzdWNjZXNzGAEgASgI", + "EkgKDGZhaWx1cmVfa2luZBgCIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21t", + "YW5kLnYxLlZlcmlmeUZhaWx1cmVLaW5kVmFsdWUSDQoFZXJyb3IYAyABKAkS", + "OwoEY2VydBgEIAEoCzItLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNl", + "cnZlckNlcnRJbmZvRHRvInUKGVRydXN0U2VydmVyQ2VydENvbW1hbmREdG8S", + "FwoPY29ubmVjdGlvbl9uYW1lGAEgASgJEhIKCmRlcl9iYXNlNjQYAiABKAkS", + "EgoKdGh1bWJwcmludBgDIAEoCRIXCg9zaXRlX2lkZW50aWZpZXIYBCABKAki", + "NAoZTGlzdFNlcnZlckNlcnRzQ29tbWFuZER0bxIXCg9zaXRlX2lkZW50aWZp", + "ZXIYASABKAkiSQoaUmVtb3ZlU2VydmVyQ2VydENvbW1hbmREdG8SEgoKdGh1", + "bWJwcmludBgBIAEoCRIXCg9zaXRlX2lkZW50aWZpZXIYAiABKAkiwgEKElRy", + "dXN0ZWRDZXJ0SW5mb0R0bxISCgp0aHVtYnByaW50GAEgASgJEg8KB3N1Ympl", + "Y3QYAiABKAkSDgoGaXNzdWVyGAMgASgJEjIKDm5vdF9iZWZvcmVfdXRjGAQg", + "ASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIxCg1ub3RfYWZ0ZXJf", + "dXRjGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIQCghyZWpl", + "Y3RlZBgGIAEoCCJXChZUcnVzdGVkQ2VydEluZm9MaXN0RHRvEj0KBWl0ZW1z", + "GAEgAygLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJ1c3RlZENl", + "cnRJbmZvRHRvIncKEkNlcnRUcnVzdFJlc3VsdER0bxIPCgdzdWNjZXNzGAEg", + "ASgIEg0KBWVycm9yGAIgASgJEkEKBWNlcnRzGAMgASgLMjIuc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuVHJ1c3RlZENlcnRJbmZvTGlzdER0byK9AQoS", + "V3JpdGVUYWdSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhcK", + "D2Nvbm5lY3Rpb25fbmFtZRgCIAEoCRIQCgh0YWdfcGF0aBgDIAEoCRI1CgV2", + "YWx1ZRgEIAEoCzImLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3Nl", + "VmFsdWUSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp", + "bWVzdGFtcCKEAQoTV3JpdGVUYWdSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlv", + "bl9pZBgBIAEoCRIPCgdzdWNjZXNzGAIgASgIEhUKDWVycm9yX21lc3NhZ2UY", + "AyABKAkSLQoJdGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp", + "bWVzdGFtcCKgBQoMT3BjVWFSZXF1ZXN0EkcKC2Jyb3dzZV9ub2RlGAEgASgL", + "MjAuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQnJvd3NlTm9kZUNvbW1h", + "bmREdG9IABJYChRzZWFyY2hfYWRkcmVzc19zcGFjZRgCIAEoCzI4LnNjYWRh", + "YnJpZGdlLnNpdGVjb21tYW5kLnYxLlNlYXJjaEFkZHJlc3NTcGFjZUNvbW1h", + "bmREdG9IABJOCg9yZWFkX3RhZ192YWx1ZXMYAyABKAsyMy5zY2FkYWJyaWRn", + "ZS5zaXRlY29tbWFuZC52MS5SZWFkVGFnVmFsdWVzQ29tbWFuZER0b0gAEk8K", + "D3ZlcmlmeV9lbmRwb2ludBgEIAEoCzI0LnNjYWRhYnJpZGdlLnNpdGVjb21t", + "YW5kLnYxLlZlcmlmeUVuZHBvaW50Q29tbWFuZER0b0gAElIKEXRydXN0X3Nl", + "cnZlcl9jZXJ0GAUgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "VHJ1c3RTZXJ2ZXJDZXJ0Q29tbWFuZER0b0gAElIKEWxpc3Rfc2VydmVyX2Nl", + "cnRzGAYgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlzdFNl", + "cnZlckNlcnRzQ29tbWFuZER0b0gAElQKEnJlbW92ZV9zZXJ2ZXJfY2VydBgH", + "IAEoCzI2LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJlbW92ZVNlcnZl", + "ckNlcnRDb21tYW5kRHRvSAASQwoJd3JpdGVfdGFnGAggASgLMi4uc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuV3JpdGVUYWdSZXF1ZXN0RHRvSABCCQoH", + "Y29tbWFuZCLhAwoKT3BjVWFSZXBseRJGCgticm93c2Vfbm9kZRgBIAEoCzIv", + "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkJyb3dzZU5vZGVSZXN1bHRE", + "dG9IABJXChRzZWFyY2hfYWRkcmVzc19zcGFjZRgCIAEoCzI3LnNjYWRhYnJp", + "ZGdlLnNpdGVjb21tYW5kLnYxLlNlYXJjaEFkZHJlc3NTcGFjZVJlc3VsdER0", + "b0gAEk0KD3JlYWRfdGFnX3ZhbHVlcxgDIAEoCzIyLnNjYWRhYnJpZGdlLnNp", + "dGVjb21tYW5kLnYxLlJlYWRUYWdWYWx1ZXNSZXN1bHREdG9IABJOCg92ZXJp", + "ZnlfZW5kcG9pbnQYBCABKAsyMy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5WZXJpZnlFbmRwb2ludFJlc3VsdER0b0gAEkQKCmNlcnRfdHJ1c3QYBSAB", + "KAsyLi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5DZXJ0VHJ1c3RSZXN1", + "bHREdG9IABJECgl3cml0ZV90YWcYBiABKAsyLy5zY2FkYWJyaWRnZS5zaXRl", + "Y29tbWFuZC52MS5Xcml0ZVRhZ1Jlc3BvbnNlRHRvSABCBwoFcmVwbHkixQIK", + "F0V2ZW50TG9nUXVlcnlSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg", + "ASgJEg8KB3NpdGVfaWQYAiABKAkSKAoEZnJvbRgDIAEoCzIaLmdvb2dsZS5w", + "cm90b2J1Zi5UaW1lc3RhbXASJgoCdG8YBCABKAsyGi5nb29nbGUucHJvdG9i", + "dWYuVGltZXN0YW1wEhIKCmV2ZW50X3R5cGUYBSABKAkSEAoIc2V2ZXJpdHkY", + "BiABKAkSEwoLaW5zdGFuY2VfaWQYByABKAkSFgoOa2V5d29yZF9maWx0ZXIY", + "CCABKAkSGgoSY29udGludWF0aW9uX3Rva2VuGAkgASgJEhEKCXBhZ2Vfc2l6", + "ZRgKIAEoBRItCgl0aW1lc3RhbXAYCyABKAsyGi5nb29nbGUucHJvdG9idWYu", + "VGltZXN0YW1wIroBChBFdmVudExvZ0VudHJ5RHRvEgoKAmlkGAEgASgJEi0K", + "CXRpbWVzdGFtcBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAS", + "EgoKZXZlbnRfdHlwZRgDIAEoCRIQCghzZXZlcml0eRgEIAEoCRITCgtpbnN0", + "YW5jZV9pZBgFIAEoCRIOCgZzb3VyY2UYBiABKAkSDwoHbWVzc2FnZRgHIAEo", + "CRIPCgdkZXRhaWxzGAggASgJIocCChhFdmVudExvZ1F1ZXJ5UmVzcG9uc2VE", + "dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRI9", + "CgdlbnRyaWVzGAMgAygLMiwuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "RXZlbnRMb2dFbnRyeUR0bxIaChJjb250aW51YXRpb25fdG9rZW4YBCABKAkS", + "EAoIaGFzX21vcmUYBSABKAgSDwoHc3VjY2VzcxgGIAEoCBIVCg1lcnJvcl9t", + "ZXNzYWdlGAcgASgJEi0KCXRpbWVzdGFtcBgIIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXAiZAoXRGVidWdTbmFwc2hvdFJlcXVlc3REdG8SHAoU", + "aW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSFgoOY29ycmVsYXRpb25faWQY", + "AiABKAkSEwoLYWxhcm1zX29ubHkYAyABKAgiVAocU3Vic2NyaWJlRGVidWdW", + "aWV3UmVxdWVzdER0bxIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgBIAEoCRIW", + "Cg5jb3JyZWxhdGlvbl9pZBgCIAEoCSJWCh5VbnN1YnNjcmliZURlYnVnVmll", + "d1JlcXVlc3REdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSFgoO", + "Y29ycmVsYXRpb25faWQYAiABKAkiHAoaVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdB", + "Y2tEdG8i1AEKFkFsYXJtQ29uZGl0aW9uU3RhdGVEdG8SDgoGYWN0aXZlGAEg", + "ASgIEhQKDGFja25vd2xlZGdlZBgCIAEoCBItCgljb25maXJtZWQYAyABKAsy", + "Gi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlEj8KBnNoZWx2ZRgEIAEoDjIv", + "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtU2hlbHZlU3RhdGVE", + "dG8SEgoKc3VwcHJlc3NlZBgFIAEoCBIQCghzZXZlcml0eRgGIAEoBSLdAQoW", + "RGVidWdBdHRyaWJ1dGVWYWx1ZUR0bxIcChRpbnN0YW5jZV91bmlxdWVfbmFt", + "ZRgBIAEoCRIWCg5hdHRyaWJ1dGVfcGF0aBgCIAEoCRIWCg5hdHRyaWJ1dGVf", + "bmFtZRgDIAEoCRI1CgV2YWx1ZRgEIAEoCzImLnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLkxvb3NlVmFsdWUSDwoHcXVhbGl0eRgFIAEoCRItCgl0aW1l", + "c3RhbXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIq8FChJE", + "ZWJ1Z0FsYXJtU3RhdGVEdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASAB", + "KAkSEgoKYWxhcm1fbmFtZRgCIAEoCRI4CgVzdGF0ZRgDIAEoDjIpLnNjYWRh", + "YnJpZGdlLnNpdGVjb21tYW5kLnYxLkFsYXJtU3RhdGVEdG8SEAoIcHJpb3Jp", + "dHkYBCABKAUSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVm", + "LlRpbWVzdGFtcBI4CgVsZXZlbBgGIAEoDjIpLnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLkFsYXJtTGV2ZWxEdG8SDwoHbWVzc2FnZRgHIAEoCRI2CgRr", + "aW5kGAggASgOMiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuQWxhcm1L", + "aW5kRHRvEkUKCWNvbmRpdGlvbhgJIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLkFsYXJtQ29uZGl0aW9uU3RhdGVEdG8SGAoQc291cmNlX3Jl", + "ZmVyZW5jZRgKIAEoCRIXCg9hbGFybV90eXBlX25hbWUYCyABKAkSEAoIY2F0", + "ZWdvcnkYDCABKAkSFQoNb3BlcmF0b3JfdXNlchgNIAEoCRIYChBvcGVyYXRv", + "cl9jb21tZW50GA4gASgJEjcKE29yaWdpbmFsX3JhaXNlX3RpbWUYDyABKAsy", + "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhUKDWN1cnJlbnRfdmFsdWUY", + "ECABKAkSEwoLbGltaXRfdmFsdWUYESABKAkSJAocbmF0aXZlX3NvdXJjZV9j", + "YW5vbmljYWxfbmFtZRgSIAEoCRIhChlpc19jb25maWd1cmVkX3BsYWNlaG9s", + "ZGVyGBMgASgIIpwCChREZWJ1Z1ZpZXdTbmFwc2hvdER0bxIcChRpbnN0YW5j", + "ZV91bmlxdWVfbmFtZRgBIAEoCRJMChBhdHRyaWJ1dGVfdmFsdWVzGAIgAygL", + "MjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdBdHRyaWJ1dGVW", + "YWx1ZUR0bxJECgxhbGFybV9zdGF0ZXMYAyADKAsyLi5zY2FkYWJyaWRnZS5z", + "aXRlY29tbWFuZC52MS5EZWJ1Z0FsYXJtU3RhdGVEdG8SNgoSc25hcHNob3Rf", + "dGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIa", + "ChJpbnN0YW5jZV9ub3RfZm91bmQYBSABKAgi8AIKDFF1ZXJ5UmVxdWVzdBJO", + "Cg9ldmVudF9sb2dfcXVlcnkYASABKAsyMy5zY2FkYWJyaWRnZS5zaXRlY29t", + "bWFuZC52MS5FdmVudExvZ1F1ZXJ5UmVxdWVzdER0b0gAEk0KDmRlYnVnX3Nu", + "YXBzaG90GAIgASgLMjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVi", + "dWdTbmFwc2hvdFJlcXVlc3REdG9IABJYChRzdWJzY3JpYmVfZGVidWdfdmll", + "dxgDIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlN1YnNjcmli", + "ZURlYnVnVmlld1JlcXVlc3REdG9IABJcChZ1bnN1YnNjcmliZV9kZWJ1Z192", + "aWV3GAQgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVW5zdWJz", + "Y3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKRAgoKUXVl", + "cnlSZXBseRJPCg9ldmVudF9sb2dfcXVlcnkYASABKAsyNC5zY2FkYWJyaWRn", + "ZS5zaXRlY29tbWFuZC52MS5FdmVudExvZ1F1ZXJ5UmVzcG9uc2VEdG9IABJP", + "ChNkZWJ1Z192aWV3X3NuYXBzaG90GAIgASgLMjAuc2NhZGFicmlkZ2Uuc2l0", + "ZWNvbW1hbmQudjEuRGVidWdWaWV3U25hcHNob3REdG9IABJYChZ1bnN1YnNj", + "cmliZV9kZWJ1Z192aWV3GAMgASgLMjYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", + "bmQudjEuVW5zdWJzY3JpYmVEZWJ1Z1ZpZXdBY2tEdG9IAEIHCgVyZXBseSKe", + "AQocUGFya2VkTWVzc2FnZVF1ZXJ5UmVxdWVzdER0bxIWCg5jb3JyZWxhdGlv", + "bl9pZBgBIAEoCRIPCgdzaXRlX2lkGAIgASgJEhMKC3BhZ2VfbnVtYmVyGAMg", + "ASgFEhEKCXBhZ2Vfc2l6ZRgEIAEoBRItCgl0aW1lc3RhbXAYBSABKAsyGi5n", + "b29nbGUucHJvdG9idWYuVGltZXN0YW1wIvICChVQYXJrZWRNZXNzYWdlRW50", + "cnlEdG8SEgoKbWVzc2FnZV9pZBgBIAEoCRIVCg10YXJnZXRfc3lzdGVtGAIg", + "ASgJEhMKC21ldGhvZF9uYW1lGAMgASgJEhUKDWVycm9yX21lc3NhZ2UYBCAB", + "KAkSFQoNYXR0ZW1wdF9jb3VudBgFIAEoBRI2ChJvcmlnaW5hbF90aW1lc3Rh", + "bXAYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjoKFmxhc3Rf", + "YXR0ZW1wdF90aW1lc3RhbXAYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGlt", + "ZXN0YW1wEhQKDG1heF9hdHRlbXB0cxgIIAEoBRJICghjYXRlZ29yeRgJIAEo", + "DjI2LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlN0b3JlQW5kRm9yd2Fy", + "ZENhdGVnb3J5RHRvEhcKD29yaWdpbl9pbnN0YW5jZRgKIAEoCSKhAgodUGFy", + "a2VkTWVzc2FnZVF1ZXJ5UmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQY", + "ASABKAkSDwoHc2l0ZV9pZBgCIAEoCRJDCghtZXNzYWdlcxgDIAMoCzIxLnNj", + "YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VFbnRyeUR0", + "bxITCgt0b3RhbF9jb3VudBgEIAEoBRITCgtwYWdlX251bWJlchgFIAEoBRIR", + "CglwYWdlX3NpemUYBiABKAUSDwoHc3VjY2VzcxgHIAEoCBIVCg1lcnJvcl9t", + "ZXNzYWdlGAggASgJEi0KCXRpbWVzdGFtcBgJIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXAiigEKHFBhcmtlZE1lc3NhZ2VSZXRyeVJlcXVlc3RE", + "dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRIS", + "CgptZXNzYWdlX2lkGAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2ds", + "ZS5wcm90b2J1Zi5UaW1lc3RhbXAiXwodUGFya2VkTWVzc2FnZVJldHJ5UmVz", + "cG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgC", + "IAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJIowBCh5QYXJrZWRNZXNzYWdl", + "RGlzY2FyZFJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoH", + "c2l0ZV9pZBgCIAEoCRISCgptZXNzYWdlX2lkGAMgASgJEi0KCXRpbWVzdGFt", + "cBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiYQofUGFya2Vk", + "TWVzc2FnZURpc2NhcmRSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgB", + "IAEoCRIPCgdzdWNjZXNzGAIgASgIEhUKDWVycm9yX21lc3NhZ2UYAyABKAki", + "TwoXUmV0cnlQYXJrZWRPcGVyYXRpb25EdG8SFgoOY29ycmVsYXRpb25faWQY", + "ASABKAkSHAoUdHJhY2tlZF9vcGVyYXRpb25faWQYAiABKAkiUQoZRGlzY2Fy", + "ZFBhcmtlZE9wZXJhdGlvbkR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIc", + "ChR0cmFja2VkX29wZXJhdGlvbl9pZBgCIAEoCSJdChtQYXJrZWRPcGVyYXRp", + "b25BY3Rpb25BY2tEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHYXBw", + "bGllZBgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJIt4DCg1QYXJrZWRS", + "ZXF1ZXN0ElgKFHBhcmtlZF9tZXNzYWdlX3F1ZXJ5GAEgASgLMjguc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVF1ZXJ5UmVxdWVz", + "dER0b0gAElgKFHBhcmtlZF9tZXNzYWdlX3JldHJ5GAIgASgLMjguc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVJldHJ5UmVxdWVz", + "dER0b0gAElwKFnBhcmtlZF9tZXNzYWdlX2Rpc2NhcmQYAyABKAsyOi5zY2Fk", + "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRNZXNzYWdlRGlzY2FyZFJl", + "cXVlc3REdG9IABJVChZyZXRyeV9wYXJrZWRfb3BlcmF0aW9uGAQgASgLMjMu", + "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUmV0cnlQYXJrZWRPcGVyYXRp", + "b25EdG9IABJZChhkaXNjYXJkX3BhcmtlZF9vcGVyYXRpb24YBSABKAsyNS5z", + "Y2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5EaXNjYXJkUGFya2VkT3BlcmF0", + "aW9uRHRvSABCCQoHY29tbWFuZCKHAwoLUGFya2VkUmVwbHkSWQoUcGFya2Vk", + "X21lc3NhZ2VfcXVlcnkYASABKAsyOS5zY2FkYWJyaWRnZS5zaXRlY29tbWFu", + "ZC52MS5QYXJrZWRNZXNzYWdlUXVlcnlSZXNwb25zZUR0b0gAElkKFHBhcmtl", + "ZF9tZXNzYWdlX3JldHJ5GAIgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", + "bmQudjEuUGFya2VkTWVzc2FnZVJldHJ5UmVzcG9uc2VEdG9IABJdChZwYXJr", + "ZWRfbWVzc2FnZV9kaXNjYXJkGAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNv", + "bW1hbmQudjEuUGFya2VkTWVzc2FnZURpc2NhcmRSZXNwb25zZUR0b0gAEloK", + "F3BhcmtlZF9vcGVyYXRpb25fYWN0aW9uGAQgASgLMjcuc2NhZGFicmlkZ2Uu", + "c2l0ZWNvbW1hbmQudjEuUGFya2VkT3BlcmF0aW9uQWN0aW9uQWNrRHRvSABC", + "BwoFcmVwbHki7QEKFVJvdXRlVG9DYWxsUmVxdWVzdER0bxIWCg5jb3JyZWxh", + "dGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRIT", + "CgtzY3JpcHRfbmFtZRgDIAEoCRI9CgpwYXJhbWV0ZXJzGAQgASgLMikuc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZU1hcBItCgl0aW1l", + "c3RhbXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKE3Bh", + "cmVudF9leGVjdXRpb25faWQYBiABKAkixQEKFlJvdXRlVG9DYWxsUmVzcG9u", + "c2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEo", + "CBI8CgxyZXR1cm5fdmFsdWUYAyABKAsyJi5zY2FkYWJyaWRnZS5zaXRlY29t", + "bWFuZC52MS5Mb29zZVZhbHVlEhUKDWVycm9yX21lc3NhZ2UYBCABKAkSLQoJ", + "dGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK7", + "AQoeUm91dGVUb0dldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0", + "aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEhcK", + "D2F0dHJpYnV0ZV9uYW1lcxgDIAMoCRItCgl0aW1lc3RhbXAYBCABKAsyGi5n", + "b29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKE3BhcmVudF9leGVjdXRpb25f", + "aWQYBSABKAkiywEKH1JvdXRlVG9HZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8S", + "FgoOY29ycmVsYXRpb25faWQYASABKAkSOQoGdmFsdWVzGAIgASgLMikuc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZU1hcBIPCgdzdWNj", + "ZXNzGAMgASgIEhUKDWVycm9yX21lc3NhZ2UYBCABKAkSLQoJdGltZXN0YW1w", + "GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLFAgoeUm91dGVU", + "b1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg", + "ASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEmkKEGF0dHJpYnV0", + "ZV92YWx1ZXMYAyADKAsyTy5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5S", + "b3V0ZVRvU2V0QXR0cmlidXRlc1JlcXVlc3REdG8uQXR0cmlidXRlVmFsdWVz", + "RW50cnkSLQoJdGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp", + "bWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9uX2lkGAUgASgJGjYKFEF0dHJp", + "YnV0ZVZhbHVlc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToC", + "OAEikAEKH1JvdXRlVG9TZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29y", + "cmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIVCg1lcnJvcl9t", + "ZXNzYWdlGAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXAiwwIKIVJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVx", + "dWVzdER0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91", + "bmlxdWVfbmFtZRgCIAEoCRIWCg5hdHRyaWJ1dGVfbmFtZRgDIAEoCRI6ChR0", + "YXJnZXRfdmFsdWVfZW5jb2RlZBgEIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5T", + "dHJpbmdWYWx1ZRIqCgd0aW1lb3V0GAUgASgLMhkuZ29vZ2xlLnByb3RvYnVm", + "LkR1cmF0aW9uEi0KCXRpbWVzdGFtcBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1", + "Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4ZWN1dGlvbl9pZBgHIAEoCRIcChRy", + "ZXF1aXJlX2dvb2RfcXVhbGl0eRgIIAEoCCL/AQoiUm91dGVUb1dhaXRGb3JB", + "dHRyaWJ1dGVSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIP", + "CgdtYXRjaGVkGAIgASgIEjUKBXZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uu", + "c2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZRIPCgdxdWFsaXR5GAQgASgJEhEK", + "CXRpbWVkX291dBgFIAEoCBIPCgdzdWNjZXNzGAYgASgIEhUKDWVycm9yX21l", + "c3NhZ2UYByABKAkSLQoJdGltZXN0YW1wGAggASgLMhouZ29vZ2xlLnByb3Rv", + "YnVmLlRpbWVzdGFtcCKJAwoMUm91dGVSZXF1ZXN0EkoKDXJvdXRlX3RvX2Nh", + "bGwYASABKAsyMS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRv", + "Q2FsbFJlcXVlc3REdG9IABJdChdyb3V0ZV90b19nZXRfYXR0cmlidXRlcxgC", + "IAEoCzI6LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9HZXRB", + "dHRyaWJ1dGVzUmVxdWVzdER0b0gAEl0KF3JvdXRlX3RvX3NldF9hdHRyaWJ1", + "dGVzGAMgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVU", + "b1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvSAASZAobcm91dGVfdG9fd2FpdF9m", + "b3JfYXR0cmlidXRlGAQgASgLMj0uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", + "djEuUm91dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXF1ZXN0RHRvSABCCQoHY29t", + "bWFuZCKJAwoKUm91dGVSZXBseRJLCg1yb3V0ZV90b19jYWxsGAEgASgLMjIu", + "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0NhbGxSZXNwb25z", + "ZUR0b0gAEl4KF3JvdXRlX3RvX2dldF9hdHRyaWJ1dGVzGAIgASgLMjsuc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0dldEF0dHJpYnV0ZXNS", + "ZXNwb25zZUR0b0gAEl4KF3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgL", + "Mjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJp", + "YnV0ZXNSZXNwb25zZUR0b0gAEmUKG3JvdXRlX3RvX3dhaXRfZm9yX2F0dHJp", + "YnV0ZRgEIAEoCzI+LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRl", + "VG9XYWl0Rm9yQXR0cmlidXRlUmVzcG9uc2VEdG9IAEIHCgVyZXBseSJBChZU", + "cmlnZ2VyU2l0ZUZhaWxvdmVyRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJ", + "Eg8KB3NpdGVfaWQYAiABKAkibQoSU2l0ZUZhaWxvdmVyQWNrRHRvEhYKDmNv", + "cnJlbGF0aW9uX2lkGAEgASgJEhAKCGFjY2VwdGVkGAIgASgIEhYKDnRhcmdl", + "dF9hZGRyZXNzGAMgASgJEhUKDWVycm9yX21lc3NhZ2UYBCABKAkqywEKE0Rl", + "cGxveW1lbnRTdGF0dXNEdG8SJQohREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1VO", + "U1BFQ0lGSUVEEAASIQodREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1BFTkRJTkcQ", + "ARIlCiFERVBMT1lNRU5UX1NUQVRVU19EVE9fSU5fUFJPR1JFU1MQAhIhCh1E", + "RVBMT1lNRU5UX1NUQVRVU19EVE9fU1VDQ0VTUxADEiAKHERFUExPWU1FTlRf", + "U1RBVFVTX0RUT19GQUlMRUQQBCrEAQoSQnJvd3NlTm9kZUNsYXNzRHRvEiUK", + "IUJST1dTRV9OT0RFX0NMQVNTX0RUT19VTlNQRUNJRklFRBAAEiAKHEJST1dT", + "RV9OT0RFX0NMQVNTX0RUT19PQkpFQ1QQARIiCh5CUk9XU0VfTk9ERV9DTEFT", + "U19EVE9fVkFSSUFCTEUQAhIgChxCUk9XU0VfTk9ERV9DTEFTU19EVE9fTUVU", + "SE9EEAMSHwobQlJPV1NFX05PREVfQ0xBU1NfRFRPX09USEVSEAQqoQIKFEJy", + "b3dzZUZhaWx1cmVLaW5kRHRvEicKI0JST1dTRV9GQUlMVVJFX0tJTkRfRFRP", + "X1VOU1BFQ0lGSUVEEAASMAosQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fQ09O", + "TkVDVElPTl9OT1RfRk9VTkQQARI0CjBCUk9XU0VfRkFJTFVSRV9LSU5EX0RU", + "T19DT05ORUNUSU9OX05PVF9DT05ORUNURUQQAhIpCiVCUk9XU0VfRkFJTFVS", + "RV9LSU5EX0RUT19OT1RfQlJPV1NBQkxFEAMSIwofQlJPV1NFX0ZBSUxVUkVf", + "S0lORF9EVE9fVElNRU9VVBAEEigKJEJST1dTRV9GQUlMVVJFX0tJTkRfRFRP", + "X1NFUlZFUl9FUlJPUhAFKqoCChtSZWFkVGFnVmFsdWVzRmFpbHVyZUtpbmRE", + "dG8SMAosUkVBRF9UQUdfVkFMVUVTX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVD", + "SUZJRUQQABI5CjVSRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19D", + "T05ORUNUSU9OX05PVF9GT1VORBABEj0KOVJFQURfVEFHX1ZBTFVFU19GQUlM", + "VVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05fTk9UX0NPTk5FQ1RFRBACEiwKKFJF", + "QURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX1RJTUVPVVQQAxIxCi1S", + "RUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19TRVJWRVJfRVJST1IQ", + "BCqTAgoUVmVyaWZ5RmFpbHVyZUtpbmREdG8SJwojVkVSSUZZX0ZBSUxVUkVf", + "S0lORF9EVE9fVU5TUEVDSUZJRUQQABInCiNWRVJJRllfRkFJTFVSRV9LSU5E", + "X0RUT19VTlJFQUNIQUJMRRABEicKI1ZFUklGWV9GQUlMVVJFX0tJTkRfRFRP", + "X0FVVEhfRkFJTEVEEAISMQotVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5U", + "UlVTVEVEX0NFUlRJRklDQVRFEAMSIwofVkVSSUZZX0ZBSUxVUkVfS0lORF9E", + "VE9fVElNRU9VVBAEEigKJFZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZF", + "Ul9FUlJPUhAFKuUBChpTdG9yZUFuZEZvcndhcmRDYXRlZ29yeUR0bxIuCipT", + "VE9SRV9BTkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fVU5TUEVDSUZJRUQQABIy", + "Ci5TVE9SRV9BTkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fRVhURVJOQUxfU1lT", + "VEVNEAESLworU1RPUkVfQU5EX0ZPUldBUkRfQ0FURUdPUllfRFRPX05PVElG", + "SUNBVElPThACEjIKLlNUT1JFX0FORF9GT1JXQVJEX0NBVEVHT1JZX0RUT19D", + "QUNIRURfREJfV1JJVEUQAypoCg1BbGFybVN0YXRlRHRvEh8KG0FMQVJNX1NU", + "QVRFX0RUT19VTlNQRUNJRklFRBAAEhoKFkFMQVJNX1NUQVRFX0RUT19BQ1RJ", + "VkUQARIaChZBTEFSTV9TVEFURV9EVE9fTk9STUFMEAIquQEKDUFsYXJtTGV2", + "ZWxEdG8SHwobQUxBUk1fTEVWRUxfRFRPX1VOU1BFQ0lGSUVEEAASGAoUQUxB", + "Uk1fTEVWRUxfRFRPX05PTkUQARIXChNBTEFSTV9MRVZFTF9EVE9fTE9XEAIS", + "GwoXQUxBUk1fTEVWRUxfRFRPX0xPV19MT1cQAxIYChRBTEFSTV9MRVZFTF9E", + "VE9fSElHSBAEEh0KGUFMQVJNX0xFVkVMX0RUT19ISUdIX0hJR0gQBSqSAQoM", + "QWxhcm1LaW5kRHRvEh4KGkFMQVJNX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAAS", + "GwoXQUxBUk1fS0lORF9EVE9fQ09NUFVURUQQARIgChxBTEFSTV9LSU5EX0RU", + "T19OQVRJVkVfT1BDX1VBEAISIwofQUxBUk1fS0lORF9EVE9fTkFUSVZFX01Y", + "X0FDQ0VTUxADKugBChNBbGFybVNoZWx2ZVN0YXRlRHRvEiYKIkFMQVJNX1NI", + "RUxWRV9TVEFURV9EVE9fVU5TUEVDSUZJRUQQABIkCiBBTEFSTV9TSEVMVkVf", + "U1RBVEVfRFRPX1VOU0hFTFZFRBABEisKJ0FMQVJNX1NIRUxWRV9TVEFURV9E", + "VE9fT05FX1NIT1RfU0hFTFZFRBACEigKJEFMQVJNX1NIRUxWRV9TVEFURV9E", + "VE9fVElNRURfU0hFTFZFRBADEiwKKEFMQVJNX1NIRUxWRV9TVEFURV9EVE9f", + "UEVSTUFORU5UX1NIRUxWRUQQBDKEBQoSU2l0ZUNvbW1hbmRTZXJ2aWNlEmwK", + "EEV4ZWN1dGVMaWZlY3ljbGUSLC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5MaWZlY3ljbGVSZXF1ZXN0Giouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", + "djEuTGlmZWN5Y2xlUmVwbHkSYAoMRXhlY3V0ZU9wY1VhEiguc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFSZXF1ZXN0GiYuc2NhZGFicmlkZ2Uu", + "c2l0ZWNvbW1hbmQudjEuT3BjVWFSZXBseRJgCgxFeGVjdXRlUXVlcnkSKC5z", + "Y2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcXVlc3QaJi5zY2Fk", + "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcGx5EmMKDUV4ZWN1dGVQ", + "YXJrZWQSKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRSZXF1", + "ZXN0Gicuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkUmVwbHkS", + "YAoMRXhlY3V0ZVJvdXRlEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "Um91dGVSZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91", + "dGVSZXBseRJ1Cg9UcmlnZ2VyRmFpbG92ZXISMi5zY2FkYWJyaWRnZS5zaXRl", + "Y29tbWFuZC52MS5UcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvGi4uc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuU2l0ZUZhaWxvdmVyQWNrRHRvQiuqAihaQi5N", + "T00uV1cuU2NhZGFCcmlkZ2UuQ29tbXVuaWNhdGlvbi5HcnBjYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeClassDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ReadTagValuesFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.VerifyFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.StoreAndForwardCategoryDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmLevelDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmShelveStateDto), }, null, new pbr::GeneratedClrTypeInfo[] { @@ -509,7 +510,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeleteInstanceCommandDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeleteInstanceCommandDto.Parser, new[]{ "CommandId", "InstanceUniqueName", "Timestamp" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStateQueryRequestDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStateQueryRequestDto.Parser, new[]{ "CorrelationId", "InstanceUniqueName", "Timestamp" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SharedScriptArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SharedScriptArtifactDto.Parser, new[]{ "Name", "Code", "ParameterDefinitions", "ReturnDefinition" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ExternalSystemArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ExternalSystemArtifactDto.Parser, new[]{ "Name", "EndpointUrl", "AuthType", "AuthConfiguration", "MethodDefinitionsJson", "TimeoutSeconds" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ExternalSystemArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ExternalSystemArtifactDto.Parser, new[]{ "Name", "EndpointUrl", "AuthType", "AuthConfiguration", "MethodDefinitionsJson", "TimeoutSeconds", "MaxRetries", "RetryDelay" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DatabaseConnectionArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DatabaseConnectionArtifactDto.Parser, new[]{ "Name", "ConnectionString", "MaxRetries", "RetryDelay" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.NotificationListArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.NotificationListArtifactDto.Parser, new[]{ "Name", "RecipientEmails" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DataConnectionArtifactDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DataConnectionArtifactDto.Parser, new[]{ "Name", "Protocol", "PrimaryConfigurationJson", "BackupConfigurationJson", "FailoverRetryCount" }, null, null, null, null), @@ -4205,6 +4206,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { authConfiguration_ = other.authConfiguration_; methodDefinitionsJson_ = other.methodDefinitionsJson_; timeoutSeconds_ = other.timeoutSeconds_; + maxRetries_ = other.maxRetries_; + retryDelay_ = other.retryDelay_ != null ? other.retryDelay_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -4292,6 +4295,35 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { } } + /// Field number for the "max_retries" field. + public const int MaxRetriesFieldNumber = 7; + private int maxRetries_; + /// + /// Store-and-Forward retry policy for this system's cached calls. Additive (fields 7-8); + /// a pre-existing site decodes them as 0/absent, which is exactly the "unset" value that + /// makes the engine defaults apply — i.e. the old behaviour. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MaxRetries { + get { return maxRetries_; } + set { + maxRetries_ = value; + } + } + + /// Field number for the "retry_delay" field. + public const int RetryDelayFieldNumber = 8; + private global::Google.Protobuf.WellKnownTypes.Duration retryDelay_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Protobuf.WellKnownTypes.Duration RetryDelay { + get { return retryDelay_; } + set { + retryDelay_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -4313,6 +4345,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (AuthConfiguration != other.AuthConfiguration) return false; if (MethodDefinitionsJson != other.MethodDefinitionsJson) return false; if (TimeoutSeconds != other.TimeoutSeconds) return false; + if (MaxRetries != other.MaxRetries) return false; + if (!object.Equals(RetryDelay, other.RetryDelay)) return false; return Equals(_unknownFields, other._unknownFields); } @@ -4326,6 +4360,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (AuthConfiguration.Length != 0) hash ^= AuthConfiguration.GetHashCode(); if (MethodDefinitionsJson.Length != 0) hash ^= MethodDefinitionsJson.GetHashCode(); if (TimeoutSeconds != 0) hash ^= TimeoutSeconds.GetHashCode(); + if (MaxRetries != 0) hash ^= MaxRetries.GetHashCode(); + if (retryDelay_ != null) hash ^= RetryDelay.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -4368,6 +4404,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(48); output.WriteInt32(TimeoutSeconds); } + if (MaxRetries != 0) { + output.WriteRawTag(56); + output.WriteInt32(MaxRetries); + } + if (retryDelay_ != null) { + output.WriteRawTag(66); + output.WriteMessage(RetryDelay); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -4402,6 +4446,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(48); output.WriteInt32(TimeoutSeconds); } + if (MaxRetries != 0) { + output.WriteRawTag(56); + output.WriteInt32(MaxRetries); + } + if (retryDelay_ != null) { + output.WriteRawTag(66); + output.WriteMessage(RetryDelay); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -4430,6 +4482,12 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (TimeoutSeconds != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(TimeoutSeconds); } + if (MaxRetries != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxRetries); + } + if (retryDelay_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(RetryDelay); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -4460,6 +4518,15 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (other.TimeoutSeconds != 0) { TimeoutSeconds = other.TimeoutSeconds; } + if (other.MaxRetries != 0) { + MaxRetries = other.MaxRetries; + } + if (other.retryDelay_ != null) { + if (retryDelay_ == null) { + RetryDelay = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + RetryDelay.MergeFrom(other.RetryDelay); + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -4503,6 +4570,17 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { TimeoutSeconds = input.ReadInt32(); break; } + case 56: { + MaxRetries = input.ReadInt32(); + break; + } + case 66: { + if (retryDelay_ == null) { + RetryDelay = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(RetryDelay); + break; + } } } #endif @@ -4546,6 +4624,17 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { TimeoutSeconds = input.ReadInt32(); break; } + case 56: { + MaxRetries = input.ReadInt32(); + break; + } + case 66: { + if (retryDelay_ == null) { + RetryDelay = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(RetryDelay); + break; + } } } } diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ArtifactDeploymentService.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ArtifactDeploymentService.cs index 33cfd3f1..2034c50e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ArtifactDeploymentService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ArtifactDeploymentService.cs @@ -192,8 +192,13 @@ public class ArtifactDeploymentService m.ReturnDefinition })) : null; + // MaxRetries/RetryDelay ride along so the site's Store-and-Forward buffering honours + // the centrally-configured per-system retry policy. Before they were carried, a site + // silently fell back to the engine defaults (50 x 30 s) for every cached call, whatever + // central had configured — the DatabaseConnectionArtifact below always carried them. externalSystemArtifacts.Add(new ExternalSystemArtifact( - es.Name, es.EndpointUrl, es.AuthType, es.AuthConfiguration, methodsJson, es.TimeoutSeconds)); + es.Name, es.EndpointUrl, es.AuthType, es.AuthConfiguration, methodsJson, es.TimeoutSeconds, + es.MaxRetries, es.RetryDelay)); } // Map database connections diff --git a/src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs b/src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs index ce040715..e1fd1506 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs @@ -113,7 +113,7 @@ public static class SiteLocalDbLegacyMigrator new("external_systems", "name", [ "name", "endpoint_url", "auth_type", "auth_configuration", "method_definitions", - "updated_at", "timeout_seconds", + "updated_at", "timeout_seconds", "max_retries", "retry_delay_ms", ]), new("database_connections", "name", [ diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs index be4e1c36..572567c8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs @@ -2021,7 +2021,11 @@ public class ManagementActor : ReceiveActor var def = new ExternalSystemDefinition(cmd.Name, cmd.EndpointUrl, cmd.AuthType) { AuthConfiguration = cmd.AuthConfiguration, - TimeoutSeconds = cmd.TimeoutSeconds ?? 0 + TimeoutSeconds = cmd.TimeoutSeconds ?? 0, + // 0 / TimeSpan.Zero is the entity's "unset" value — the site gateway maps it to the + // Store-and-Forward engine defaults rather than to a literal zero budget. + MaxRetries = cmd.MaxRetries ?? 0, + RetryDelay = cmd.RetryDelay ?? TimeSpan.Zero }; await repo.AddExternalSystemAsync(def); await repo.SaveChangesAsync(); @@ -2042,6 +2046,9 @@ public class ManagementActor : ReceiveActor // secret intact (mirrors the SMTP/SMS credential preserve-if-null rule). if (cmd.AuthConfiguration is not null) def.AuthConfiguration = cmd.AuthConfiguration; if (cmd.TimeoutSeconds is { } ts) def.TimeoutSeconds = ts; + // Same preserve-if-null rule for the Store-and-Forward retry policy. + if (cmd.MaxRetries is { } mr) def.MaxRetries = mr; + if (cmd.RetryDelay is { } rd) def.RetryDelay = rd; await repo.UpdateExternalSystemAsync(def); await repo.SaveChangesAsync(); var publicShape = ExternalSystemPublicShape(def); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs index 8495149f..638b06ab 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs @@ -2155,7 +2155,8 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers foreach (var es in command.ExternalSystems) { await _storage.StoreExternalSystemAsync(es.Name, es.EndpointUrl, - es.AuthType, es.AuthConfiguration, es.MethodDefinitionsJson, es.TimeoutSeconds); + es.AuthType, es.AuthConfiguration, es.MethodDefinitionsJson, es.TimeoutSeconds, + es.MaxRetries, es.RetryDelay); } await _storage.DeleteExternalSystemsExceptAsync( diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageSchema.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageSchema.cs index b54711b8..c7698250 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageSchema.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageSchema.cs @@ -133,6 +133,28 @@ public static class SiteStorageSchema // Per-external-system call timeout (ExternalSystemGateway Timeout) — carried through the // artifact pipeline so site-side calls honor it; 0 = use the site default. AddColumnIfMissing(connection, "external_systems", "timeout_seconds", "INTEGER NOT NULL DEFAULT 0"); + + // Store-and-Forward retry policy, deployed per external system (deferred-work row 27). + // + // 0 = unset on BOTH columns, which is what makes this additive change behaviourally + // invisible until an operator actually configures a policy: an existing row backfilled + // with the DEFAULT reads back as 0, and ExternalSystemClient.CachedCallAsync maps a 0 + // to null so the engine's DefaultMaxRetries/DefaultRetryInterval still apply. (Contrast + // database_connections, whose equivalent columns default to 3/1000 — that table has + // never had an "unset means engine default" contract.) + // + // These land on a table in SiteLocalDbSetup.ReplicatedTables. That is safe and needs no + // trigger migration: RegisterReplicated re-reads PRAGMA table_info on EVERY boot and its + // install script is DROP-then-CREATE, so the capture triggers are rebuilt over the new + // column set automatically — and Apply() runs before RegisterReplicated, so the rebuild + // sees these columns on the same boot that adds them. What DOES change is the table's + // schema digest (ReplicatedTable.ComputeDigest hashes every column name + type), which + // the sync handshake compares fail-closed; a pair running mismatched builds refuses to + // sync loudly (LocalDbSchemaMismatchException) rather than corrupting anything. Both + // nodes must therefore be upgraded together — already the standing rule for a site pair + // (docs/deployment/topology-guide.md), so this introduces no new operational constraint. + AddColumnIfMissing(connection, "external_systems", "max_retries", "INTEGER NOT NULL DEFAULT 0"); + AddColumnIfMissing(connection, "external_systems", "retry_delay_ms", "INTEGER NOT NULL DEFAULT 0"); } /// diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs index 63f2c697..9e7325ca 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs @@ -647,23 +647,33 @@ public class SiteStorageService /// Authentication configuration JSON, if applicable. /// JSON representation of available method definitions, if any. /// Per-system call timeout in seconds (0 = use the site default). + /// + /// Store-and-Forward retry budget for this system's cached calls (0 = unset — the engine's + /// DefaultMaxRetries applies). + /// + /// + /// Fixed interval between Store-and-Forward retry sweeps for this system's cached calls + /// ( = unset — the engine's DefaultRetryInterval applies). + /// /// A task that completes when the external system definition has been stored or updated. public async Task StoreExternalSystemAsync( string name, string endpointUrl, string authType, string? authConfig, string? methodDefs, - int timeoutSeconds = 0) + int timeoutSeconds = 0, int maxRetries = 0, TimeSpan retryDelay = default) { await using var connection = OpenConnection(); await using var command = connection.CreateCommand(); command.CommandText = @" - INSERT INTO external_systems (name, endpoint_url, auth_type, auth_configuration, method_definitions, timeout_seconds, updated_at) - VALUES (@name, @url, @authType, @authConfig, @methodDefs, @timeoutSeconds, @updatedAt) + INSERT INTO external_systems (name, endpoint_url, auth_type, auth_configuration, method_definitions, timeout_seconds, max_retries, retry_delay_ms, updated_at) + VALUES (@name, @url, @authType, @authConfig, @methodDefs, @timeoutSeconds, @maxRetries, @retryDelayMs, @updatedAt) ON CONFLICT(name) DO UPDATE SET endpoint_url = excluded.endpoint_url, auth_type = excluded.auth_type, auth_configuration = excluded.auth_configuration, method_definitions = excluded.method_definitions, timeout_seconds = excluded.timeout_seconds, + max_retries = excluded.max_retries, + retry_delay_ms = excluded.retry_delay_ms, updated_at = excluded.updated_at"; command.Parameters.AddWithValue("@name", name); @@ -672,6 +682,8 @@ public class SiteStorageService command.Parameters.AddWithValue("@authConfig", (object?)authConfig ?? DBNull.Value); command.Parameters.AddWithValue("@methodDefs", (object?)methodDefs ?? DBNull.Value); command.Parameters.AddWithValue("@timeoutSeconds", timeoutSeconds); + command.Parameters.AddWithValue("@maxRetries", maxRetries); + command.Parameters.AddWithValue("@retryDelayMs", (long)retryDelay.TotalMilliseconds); command.Parameters.AddWithValue("@updatedAt", DateTimeOffset.UtcNow.ToString("O")); await command.ExecuteNonQueryAsync(); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SiteExternalSystemRepository.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SiteExternalSystemRepository.cs index e03801fb..fe4b738d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SiteExternalSystemRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SiteExternalSystemRepository.cs @@ -250,7 +250,13 @@ public class SiteExternalSystemRepository : IExternalSystemRepository { Id = GenerateSyntheticId(name), AuthConfiguration = reader.IsDBNull(3) ? null : reader.GetString(3), - TimeoutSeconds = reader.IsDBNull(4) ? 0 : reader.GetInt32(4) + TimeoutSeconds = reader.IsDBNull(4) ? 0 : reader.GetInt32(4), + // Deployed Store-and-Forward retry policy (deferred-work row 27). Ordinals 6/7 are + // deliberately AFTER method_definitions (5) so the pre-existing indexes are untouched. + // 0 stays 0: it is the "unset" value ExternalSystemClient.CachedCallAsync converts to + // null so the engine defaults apply. + MaxRetries = reader.IsDBNull(6) ? 0 : reader.GetInt32(6), + RetryDelay = reader.IsDBNull(7) ? TimeSpan.Zero : TimeSpan.FromMilliseconds(reader.GetInt64(7)) }; } @@ -271,7 +277,8 @@ public class SiteExternalSystemRepository : IExternalSystemRepository await using var command = connection.CreateCommand(); command.CommandText = @" - SELECT name, endpoint_url, auth_type, auth_configuration, timeout_seconds, method_definitions + SELECT name, endpoint_url, auth_type, auth_configuration, timeout_seconds, method_definitions, + max_retries, retry_delay_ms FROM external_systems"; var byName = new Dictionary(StringComparer.Ordinal); diff --git a/src/ZB.MOM.WW.ScadaBridge.Transport/Import/ArtifactDiff.cs b/src/ZB.MOM.WW.ScadaBridge.Transport/Import/ArtifactDiff.cs index cee98bf3..fd5acb02 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Transport/Import/ArtifactDiff.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Transport/Import/ArtifactDiff.cs @@ -165,6 +165,11 @@ public sealed class ArtifactDiff var changes = new List(); AddIfDifferent(changes, "BaseUrl", existing.EndpointUrl, incoming.BaseUrl); AddIfDifferent(changes, "AuthType", existing.AuthType, incoming.AuthType); + // The bundle has always CARRIED the retry policy and the importer has always APPLIED it, + // but the diff omitted it — so an import that silently changed a system's retry budget + // previewed as "Identical". Mirrors CompareDatabaseConnection below. + AddIfDifferent(changes, "MaxRetries", existing.MaxRetries, incoming.MaxRetries); + AddIfDifferent(changes, "RetryDelay", existing.RetryDelay.ToString(), incoming.RetryDelay.ToString()); // Secrets: presence-only comparison (we never echo the value in the diff). var existingHasSecret = !string.IsNullOrEmpty(existing.AuthConfiguration); diff --git a/tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/Commands/ExternalSystemRetryOptionTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/Commands/ExternalSystemRetryOptionTests.cs new file mode 100644 index 00000000..a465e55e --- /dev/null +++ b/tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/Commands/ExternalSystemRetryOptionTests.cs @@ -0,0 +1,102 @@ +using System.CommandLine; +using ZB.MOM.WW.ScadaBridge.CLI.Commands; + +namespace ZB.MOM.WW.ScadaBridge.CLI.Tests.Commands; + +/// +/// Deferred-work row 27(b): external-system create and external-system update +/// must expose the per-system Store-and-Forward retry policy. Before this the fields existed +/// on the central entity but had NO management surface at all — the only way to set them was +/// a direct DB edit of ExternalSystemDefinitions. +/// +/// The delay flag is named --retry-delay-seconds to match the sibling +/// --timeout-seconds on these same commands (the repo-wide CLI convention is an explicit +/// unit suffix), with --retry-delay kept as an alias. +/// +/// +public class ExternalSystemRetryOptionTests +{ + private static readonly Option Url = new("--url") { Recursive = true }; + private static readonly Option Format = new("--format") { Recursive = true }; + private static readonly Option Username = new("--username") { Recursive = true }; + private static readonly Option Password = new("--password") { Recursive = true }; + + private static Command Group() => ExternalSystemCommands.Build(Url, Format, Username, Password); + + private static Option? FindOption(Command command, string name) + => command.Options.SingleOrDefault(o => o.Name == name); + + [Theory] + [InlineData("create")] + [InlineData("update")] + public void HasOptionalRetryPolicyOptions(string subcommand) + { + var cmd = Group().Subcommands.Single(c => c.Name == subcommand); + + var maxRetries = FindOption(cmd, "--max-retries"); + Assert.NotNull(maxRetries); + Assert.False(maxRetries!.Required); + + var retryDelay = FindOption(cmd, "--retry-delay-seconds"); + Assert.NotNull(retryDelay); + Assert.False(retryDelay!.Required); + } + + [Fact] + public void Create_ParsesRetryPolicyValues() + { + var parse = Group().Parse(new[] + { + "create", "--name", "Sys", "--endpoint-url", "http://x", "--auth-type", "none", + "--max-retries", "8", "--retry-delay-seconds", "60", + }); + + Assert.Empty(parse.Errors); + Assert.Equal(8, parse.GetValue("--max-retries")); + Assert.Equal(60, parse.GetValue("--retry-delay-seconds")); + } + + [Fact] + public void Update_ParsesRetryPolicyValues() + { + var parse = Group().Parse(new[] + { + "update", "--id", "7", "--name", "Sys", "--endpoint-url", "http://x", + "--auth-type", "none", "--max-retries", "3", "--retry-delay-seconds", "10", + }); + + Assert.Empty(parse.Errors); + Assert.Equal(3, parse.GetValue("--max-retries")); + Assert.Equal(10, parse.GetValue("--retry-delay-seconds")); + } + + [Fact] + public void RetryDelayAliasIsAccepted() + { + var parse = Group().Parse(new[] + { + "create", "--name", "Sys", "--endpoint-url", "http://x", "--auth-type", "none", + "--retry-delay", "45", + }); + + Assert.Empty(parse.Errors); + Assert.Equal(45, parse.GetValue("--retry-delay-seconds")); + } + + /// + /// Omission must stay distinguishable from an explicit 0 — that is what makes update's + /// "omit to preserve" rule and create's "fall back to the engine default" rule work. + /// + [Fact] + public void OmittedRetryPolicy_ParsesAsNull() + { + var parse = Group().Parse(new[] + { + "create", "--name", "Sys", "--endpoint-url", "http://x", "--auth-type", "none", + }); + + Assert.Empty(parse.Errors); + Assert.Null(parse.GetValue("--max-retries")); + Assert.Null(parse.GetValue("--retry-delay-seconds")); + } +} diff --git a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs index bb9764a3..ab67bfbf 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs @@ -217,8 +217,12 @@ internal static class SiteCommandSamples private static SharedScriptArtifact SharedScript() => new("Calc", "return 1;", "{\"p\":\"int\"}", "{\"r\":\"int\"}"); + // MaxRetries/RetryDelay are non-default on purpose: they are the deferred-work-row-27 + // additions (proto fields 7-8), and the generic round-trip assertion is what pins them + // to the wire. A sample left at the defaults would round-trip vacuously. private static ExternalSystemArtifact ExternalSystem() => - new("Mes", "https://mes/api", "ApiKey", "{\"key\":\"x\"}", "[{\"name\":\"Post\"}]", 45); + new("Mes", "https://mes/api", "ApiKey", "{\"key\":\"x\"}", "[{\"name\":\"Post\"}]", 45, + MaxRetries: 12, RetryDelay: TimeSpan.FromSeconds(20)); private static DataConnectionArtifact DataConnection() => new("Plc1", "OpcUa", "{\"url\":\"opc.tcp://a\"}", "{\"url\":\"opc.tcp://b\"}", 5); diff --git a/tests/ZB.MOM.WW.ScadaBridge.DeploymentManager.Tests/ArtifactDeploymentServiceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.DeploymentManager.Tests/ArtifactDeploymentServiceTests.cs index 4726a646..ae0b4e7c 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.DeploymentManager.Tests/ArtifactDeploymentServiceTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.DeploymentManager.Tests/ArtifactDeploymentServiceTests.cs @@ -11,6 +11,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts; using ZB.MOM.WW.ScadaBridge.Communication; +using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems; namespace ZB.MOM.WW.ScadaBridge.DeploymentManager.Tests; @@ -189,6 +190,38 @@ public class ArtifactDeploymentServiceTests : TestKit await _siteRepo.Received(1).GetDataConnectionsBySiteIdAsync(3, Arg.Any()); } + /// + /// Deferred-work row 27(a): the per-system retry policy must be projected onto the + /// artifact that ships to sites. Before the fix ExternalSystemArtifact had no such + /// fields, so a centrally-configured policy never left central and every site cached call + /// silently used the engine default (50 x 30 s) — while the sibling + /// DatabaseConnectionArtifact had always carried its equivalents. + /// + [Fact] + public async Task DeployedExternalSystemArtifact_CarriesRetryPolicy() + { + _externalSystemRepo.GetAllExternalSystemsAsync(Arg.Any()).Returns( + [ + new ExternalSystemDefinition("Mes", "https://mes", "ApiKey") + { + Id = 1, + MaxRetries = 6, + RetryDelay = TimeSpan.FromSeconds(120), + }, + ]); + + var recorder = new ArtifactProbeRecorder(); + var probe = Sys.ActorOf(Props.Create(() => new ArtifactProbeActor(recorder))); + var service = CreateServiceWithCommActor(probe); + + var result = await service.RetryForSiteAsync(1, "retry-site", "admin"); + + Assert.True(result.IsSuccess); + var artifact = Assert.Single(Assert.Single(recorder.Received).ExternalSystems!); + Assert.Equal(6, artifact.MaxRetries); + Assert.Equal(TimeSpan.FromSeconds(120), artifact.RetryDelay); + } + [Fact] public async Task RetryForSiteAsync_SingleSitePath_StillRunsTheGlobalQueriesOnce() { diff --git a/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/ManagementActorTests.cs b/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/ManagementActorTests.cs index 3fde780b..0dc3d93e 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/ManagementActorTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/ManagementActorTests.cs @@ -3968,6 +3968,61 @@ public class ManagementActorTests : TestKit, IDisposable Arg.Any()); } + /// + /// Deferred-work row 27(b): the retry policy had no management surface at all — the only + /// way to set it was a direct DB edit of ExternalSystemDefinitions. Create must now + /// map both fields onto the entity. + /// + [Fact] + public void CreateExternalSystem_MapsRetryPolicy() + { + var extRepo = Substitute.For(); + _services.AddScoped(_ => extRepo); + + var actor = CreateActor(); + var envelope = Envelope( + new CreateExternalSystemCommand("Sys", "http://x", "none", null, + TimeoutSeconds: 15, MaxRetries: 8, RetryDelay: TimeSpan.FromSeconds(60)), + "Designer"); + + actor.Tell(envelope); + + var response = ExpectMsg(TimeSpan.FromSeconds(5)); + Assert.Equal(envelope.CorrelationId, response.CorrelationId); + extRepo.Received(1).AddExternalSystemAsync( + Arg.Is( + d => d.MaxRetries == 8 && d.RetryDelay == TimeSpan.FromSeconds(60)), + Arg.Any()); + } + + /// + /// The retry policy follows the same "omit to preserve" rule as TimeoutSeconds, so a + /// partial update (e.g. renaming a system) cannot silently reset it to 0. + /// + [Fact] + public void UpdateExternalSystem_NullRetryPolicy_PreservesExisting() + { + var existing = new Commons.Entities.ExternalSystems.ExternalSystemDefinition("Sys", "http://x", "none") + { + MaxRetries = 11, + RetryDelay = TimeSpan.FromSeconds(33) + }; + var extRepo = Substitute.For(); + extRepo.GetExternalSystemByIdAsync(7, Arg.Any()).Returns(existing); + _services.AddScoped(_ => extRepo); + + var actor = CreateActor(); + var envelope = Envelope( + new UpdateExternalSystemCommand(7, "Renamed", "http://x", "none", null), + "Designer"); + + actor.Tell(envelope); + + ExpectMsg(TimeSpan.FromSeconds(5)); + Assert.Equal(11, existing.MaxRetries); + Assert.Equal(TimeSpan.FromSeconds(33), existing.RetryDelay); + } + // ======================================================================== // Area management role gate (arch-review C6): reconciled to any-of // [Designer, Deployer]. The Central UI creates areas inside the Deployment diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerActorTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerActorTests.cs index 9d1258ad..c8fae91c 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerActorTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerActorTests.cs @@ -997,6 +997,35 @@ public class DeploymentManagerActorTests : TestKit, IDisposable SmtpConfigurations: null, Timestamp: DateTimeOffset.UtcNow); + /// + /// Deferred-work row 27: the per-system Store-and-Forward retry policy must survive the + /// site APPLY path, not just the storage round-trip. Before the fix + /// ExternalSystemArtifact carried no retry fields at all, so a centrally-configured + /// policy was dropped on the floor here and every cached call fell back to the engine's + /// 50 x 30 s default. + /// + [Fact] + public async Task ApplyingArtifacts_PersistsExternalSystemRetryPolicy() + { + var manager = CreateDeploymentManager(); + + manager.Tell(ArtifactsCommand("dep-es-retry", externalSystems: + [ + new ExternalSystemArtifact("MES", "https://mes", "ApiKey", null, null, 0, + MaxRetries: 9, RetryDelay: TimeSpan.FromSeconds(45)) + ])); + Assert.True(ExpectMsg(TimeSpan.FromSeconds(10)).Success); + + await using var connection = _storage.CreateConnection(); + await using var command = connection.CreateCommand(); + command.CommandText = "SELECT max_retries, retry_delay_ms FROM external_systems WHERE name = 'MES'"; + await using var reader = await command.ExecuteReaderAsync(); + + Assert.True(await reader.ReadAsync()); + Assert.Equal(9, reader.GetInt32(0)); + Assert.Equal(45_000, reader.GetInt64(1)); + } + [Fact] public async Task ApplyingArtifacts_DeletesExternalSystemsAbsentFromTheSet() { diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Repositories/SiteRepositoryTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Repositories/SiteRepositoryTests.cs index 201bf176..9c647ea9 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Repositories/SiteRepositoryTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Repositories/SiteRepositoryTests.cs @@ -86,6 +86,52 @@ public class SiteRepositoryTests : IDisposable Assert.Equal(7, found!.TimeoutSeconds); } + /// + /// Deferred-work row 27: the per-system Store-and-Forward retry policy + /// (MaxRetries/RetryDelay) must round-trip through the site SQLite store, + /// so ExternalSystemClient.CachedCallAsync can hand it to the engine instead of + /// silently falling back to DefaultMaxRetries (50) x DefaultRetryInterval (30 s). + /// Before the fix the site table had no such columns and this read back 0 / TimeSpan.Zero. + /// + [Fact] + public async Task SiteStorage_ExternalSystem_RetryPolicy_RoundTrips() + { + var storage = NewStorage(); + await storage.InitializeAsync(); + await storage.StoreExternalSystemAsync( + "MesApi", "https://mes.example.com", "ApiKey", null, null, + timeoutSeconds: 0, maxRetries: 7, retryDelay: TimeSpan.FromSeconds(90)); + + var repo = new SiteExternalSystemRepository(storage); + var found = await repo.GetExternalSystemByNameAsync("MesApi"); + + Assert.NotNull(found); + Assert.Equal(7, found!.MaxRetries); + Assert.Equal(TimeSpan.FromSeconds(90), found.RetryDelay); + } + + /// + /// The unset case stays unset: a system deployed without a retry policy must read back as + /// 0 / , which is the value the gateway translates to null so the + /// engine defaults apply. This is what makes the new columns behaviourally invisible until + /// an operator actually configures a policy. + /// + [Fact] + public async Task SiteStorage_ExternalSystem_RetryPolicy_DefaultsToUnset() + { + var storage = NewStorage(); + await storage.InitializeAsync(); + await storage.StoreExternalSystemAsync( + "PlainApi", "https://plain.example.com", "ApiKey", null, null); + + var repo = new SiteExternalSystemRepository(storage); + var found = await repo.GetExternalSystemByNameAsync("PlainApi"); + + Assert.NotNull(found); + Assert.Equal(0, found!.MaxRetries); + Assert.Equal(TimeSpan.Zero, found.RetryDelay); + } + /// /// SiteRuntime-007: the synthetic ID for an external system must be identical when /// the storage service and repository are re-created (simulating a process restart). diff --git a/tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/Import/ArtifactDiffTests.cs b/tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/Import/ArtifactDiffTests.cs index 8a5306a8..3adf39ea 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/Import/ArtifactDiffTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/Import/ArtifactDiffTests.cs @@ -9,6 +9,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; using ZB.MOM.WW.ScadaBridge.Commons.Types.Transport; using ZB.MOM.WW.ScadaBridge.Transport.Import; using ZB.MOM.WW.ScadaBridge.Transport.Serialization; +using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems; namespace ZB.MOM.WW.ScadaBridge.Transport.Tests.Import; @@ -105,6 +106,56 @@ public sealed class ArtifactDiffTests Assert.Null(item.FieldDiffJson); } + // ============ Deferred-work row 27: ES retry policy in the diff ============ + + /// + /// The bundle has always CARRIED the external-system retry policy and + /// BundleImporter has always APPLIED it, but CompareExternalSystem never + /// compared it — so an import that silently changed a system's retry budget previewed as + /// "Identical". Now that the policy actually reaches sites, an unreviewed change to it is a + /// live behaviour change, so it must show up in the preview. + /// + [Fact] + public void ExternalSystem_ChangedRetryPolicy_IsReported() + { + var existing = new ExternalSystemDefinition("Mes", "https://mes", "ApiKey") + { + MaxRetries = 3, + RetryDelay = TimeSpan.FromSeconds(5), + }; + var incoming = new ExternalSystemDto("Mes", "https://mes", "ApiKey", + MaxRetries: 9, RetryDelay: TimeSpan.FromSeconds(45), Methods: [], Secrets: null); + + var item = _diff.CompareExternalSystem(incoming, existing, []); + + Assert.Equal(ConflictKind.Modified, item.Kind); + + var maxRetries = ChangeFor(item, "MaxRetries"); + Assert.Equal("3", maxRetries.GetProperty("oldValue").GetString()); + Assert.Equal("9", maxRetries.GetProperty("newValue").GetString()); + + var retryDelay = ChangeFor(item, "RetryDelay"); + Assert.Equal(TimeSpan.FromSeconds(5).ToString(), retryDelay.GetProperty("oldValue").GetString()); + Assert.Equal(TimeSpan.FromSeconds(45).ToString(), retryDelay.GetProperty("newValue").GetString()); + } + + /// An unchanged retry policy must not manufacture a spurious diff row. + [Fact] + public void ExternalSystem_UnchangedRetryPolicy_IsIdentical() + { + var existing = new ExternalSystemDefinition("Mes", "https://mes", "ApiKey") + { + MaxRetries = 3, + RetryDelay = TimeSpan.FromSeconds(5), + }; + var incoming = new ExternalSystemDto("Mes", "https://mes", "ApiKey", + MaxRetries: 3, RetryDelay: TimeSpan.FromSeconds(5), Methods: [], Secrets: null); + + var item = _diff.CompareExternalSystem(incoming, existing, []); + + Assert.Equal(ConflictKind.Identical, item.Kind); + } + [Fact] public void ApiMethod_ModifiedScript_EmitsStructuredLineDiff() {